Browse Source

refactor: use posix_spawn instead of NSTask so we can disclaim the spawned ShipIt executable (#34059)

* refactor: use posix_spawn instead of NSTask so we can disclaim the spawned ShipIt executable (#33468)

* Update .patches
Samuel Attard 3 years ago
parent
commit
5d46db1839

+ 1 - 0
patches/squirrel.mac/.patches

@@ -1,3 +1,4 @@
 build_add_gn_config.patch
 fix_ensure_that_self_is_retained_until_the_racsignal_is_complete.patch
 fix_use_kseccschecknestedcode_kseccsstrictvalidate_in_the_sec.patch
+refactor_use_posix_spawn_instead_of_nstask_so_we_can_disclaim_the.patch

+ 101 - 0
patches/squirrel.mac/refactor_use_posix_spawn_instead_of_nstask_so_we_can_disclaim_the.patch

@@ -0,0 +1,101 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Samuel Attard <[email protected]>
+Date: Mon, 28 Mar 2022 02:36:39 -0700
+Subject: refactor: use posix_spawn instead of NSTask so we can disclaim the
+ spawned ShipIt executable
+
+This ensures that if the ShipIt executable is hotswapped it doesn't inherit TCC permissions
+
+diff --git a/Squirrel/ShipIt-main.m b/Squirrel/ShipIt-main.m
+index db246534e176f9c3ea2dd8b1c8659378fdc2435d..2c515ffdd67052a08ee8155c0e46b57e9721a0e5 100644
+--- a/Squirrel/ShipIt-main.m
++++ b/Squirrel/ShipIt-main.m
+@@ -13,6 +13,9 @@
+ #import <ReactiveObjC/RACSignal+Operations.h>
+ #import <ReactiveObjC/RACScheduler.h>
+ 
++#include <spawn.h>
++#include <sys/wait.h>
++
+ #import "NSError+SQRLVerbosityExtensions.h"
+ #import "RACSignal+SQRLTransactionExtensions.h"
+ #import "SQRLInstaller.h"
+@@ -20,6 +23,20 @@
+ #import "SQRLTerminationListener.h"
+ #import "SQRLShipItRequest.h"
+ 
++extern char **environ;
++
++int responsibility_spawnattrs_setdisclaim(posix_spawnattr_t attrs, int disclaim)
++__attribute__((availability(macos,introduced=10.14),weak_import));
++
++#define CHECK_ERR(expr) \
++	{ \
++		int err = (expr); \
++    if (err) { \
++        fprintf(stderr, "%s: %s", #expr, strerror(err)); \
++        exit(err); \
++    } \
++	}
++
+ // The maximum number of times ShipIt should run the same installation state, in
+ // an attempt to update.
+ //
+@@ -136,11 +153,37 @@ static void installRequest(RACSignal *readRequestSignal, NSString *applicationId
+ 							NSString *exe = NSProcessInfo.processInfo.arguments[0];
+ 							NSLog(@"Launching new ShipIt at %@ with instructions to launch %@", exe, bundleURL);
+ 
+-							NSTask *task = [[NSTask alloc] init];
+-							[task setLaunchPath: exe];
+-							[task setArguments: @[launchSignal, bundleURL.path]];
+-							[task launch];
+-							[task waitUntilExit];
++							posix_spawnattr_t attr;
++							CHECK_ERR(posix_spawnattr_init(&attr));
++
++							if (@available(macOS 10.14, *)) {
++									// Disclaim TCC responsibilities
++									if (responsibility_spawnattrs_setdisclaim)
++											CHECK_ERR(responsibility_spawnattrs_setdisclaim(&attr, 1));
++							}
++
++							pid_t pid = 0;
++
++							const char* launchPath = [exe fileSystemRepresentation];
++							const char* signal = [launchSignal fileSystemRepresentation];
++							const char* path = [bundleURL.path fileSystemRepresentation];
++							const char* args[] = { launchPath, signal, path, 0 };
++							int status = posix_spawn(&pid, [exe UTF8String], NULL, &attr, (char *const*)args, environ);
++							if (status == 0) {
++								NSLog(@"New ShipIt pid: %i", pid);
++								do {
++									if (waitpid(pid, &status, 0) != -1) {
++										NSLog(@"ShipIt status %d", WEXITSTATUS(status));
++									} else {
++										perror("waitpid");
++										exit(1);
++									}
++								} while (!WIFEXITED(status) && !WIFSIGNALED(status));
++							} else {
++								NSLog(@"posix_spawn: %s", strerror(status));
++							}
++
++							posix_spawnattr_destroy(&attr);
+ 
+ 							NSLog(@"New ShipIt exited");
+ 						} else {
+@@ -172,7 +215,13 @@ int main(int argc, const char * argv[]) {
+ 		});
+ 
+ 		if (argc < 3) {
+-			NSLog(@"Missing launchd job label or state path for ShipIt");
++			NSLog(@"Missing launchd job label or state path for ShipIt (%d)", argc);
++			if (argc >= 1) {
++				NSLog(@"Arg 1: {%s}", argv[0]);
++			}
++			if (argc >= 2) {
++				NSLog(@"Arg 2: {%s}", argv[1]);
++			}
+ 			return EXIT_FAILURE;
+ 		}
+