diff options
-rwxr-xr-x | configure | 6 | ||||
-rw-r--r-- | darwin-bootstrap/posixspawn-hook.c | 59 | ||||
-rw-r--r-- | darwin-bootstrap/substituted.m | 44 | ||||
-rw-r--r-- | lib/darwin/xxpc.h | 4 | ||||
-rwxr-xr-x | script/gen-deb.sh | 2 | ||||
-rw-r--r-- | test/test-htab.c | 6 |
6 files changed, 82 insertions, 39 deletions
@@ -56,8 +56,12 @@ if settings.enable_werror: for mach in machs + [settings.host_machine()]: settings[mach.name].cflags = ['-Werror'] + settings[mach.name].cflags +# XXX this is a mess and wrong +flags = ['-O3'] +if settings.host_machine().is_cross(): + flags.append('-miphoneos-version-min=8.0') for i in ('cflags', 'ldflags'): - settings.host[i] = ['-miphoneos-version-min=8.0', '-O3'] + settings.host[i] + settings.host[i] = flags + settings.host[i] # todo make overridable? cc_argv = c.cc.argv() diff --git a/darwin-bootstrap/posixspawn-hook.c b/darwin-bootstrap/posixspawn-hook.c index b2a7336..50c4ca9 100644 --- a/darwin-bootstrap/posixspawn-hook.c +++ b/darwin-bootstrap/posixspawn-hook.c @@ -57,9 +57,9 @@ static int (*old_xpc_pipe_try_receive)(mach_port_t, xxpc_object_t *, mach_port_t *, void *, size_t, int); static bool g_is_launchd; -static xxpc_object_t g_argv0_to_fate; -static HTAB_STORAGE(pid_str) g_pid_to_argv0 = - HTAB_STORAGE_INIT_STATIC(&g_pid_to_argv0, pid_str); +static xxpc_object_t g_bundleid_to_fate; +static HTAB_STORAGE(pid_str) g_pid_to_bundleid = + HTAB_STORAGE_INIT_STATIC(&g_pid_to_bundleid, pid_str); static pthread_mutex_t g_dicts_lock = PTHREAD_MUTEX_INITIALIZER; static bool advance(char **strp, const char *template) { @@ -207,13 +207,15 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, static const char psh_dylib[] = "/Library/Substitute/Helpers/posixspawn-hook.dylib"; - const char *argv0 = argv[0] ?: ""; + const char *bundleid = NULL; /* which dylib should we add, if any? */ const char *dylib_to_add; if (g_is_launchd) { if (strcmp(path, "/usr/libexec/xpcproxy")) goto skip; + if (argv[0] && argv[1]) + bundleid = argv[1]; dylib_to_add = psh_dylib; } else { /* - substituted obviously doesn't want to have bundle_loader run in it @@ -242,7 +244,7 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, */ if (!strcmp(path, "/Library/Substitute/Helpers/substituted") || !strcmp(path, "/usr/sbin/notifyd") || - !strcmp(xbasename(argv0), "sshd")) + !strcmp(xbasename(argv[0] ?: ""), "sshd")) goto skip; dylib_to_add = bl_dylib; } @@ -379,9 +381,11 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, if (need_unrestrict) spawn_unrestrict(pid, !was_suspended, false); - pthread_mutex_lock(&g_dicts_lock); - *htab_setp_pid_str(&g_pid_to_argv0.h, &pid, NULL) = strdup(argv0); - pthread_mutex_unlock(&g_dicts_lock); + if (bundleid) { + pthread_mutex_lock(&g_dicts_lock); + *htab_setp_pid_str(&g_pid_to_bundleid.h, &pid, NULL) = strdup(bundleid); + pthread_mutex_unlock(&g_dicts_lock); + } goto cleanup; crap: @@ -416,17 +420,18 @@ static void after_wait_generic(pid_t pid, int stat) { return; pthread_mutex_lock(&g_dicts_lock); struct htab_bucket_pid_str *bucket = - htab_getbucket_pid_str(&g_pid_to_argv0.h, &pid); + htab_getbucket_pid_str(&g_pid_to_bundleid.h, &pid); if (!bucket) { /* probably spawned some other way / not a task */ if (IB_VERBOSE) ib_log("reaped unknown pid %d", pid); - return; + goto end; } - char *argv0 = bucket->value; - xxpc_dictionary_set_int64(g_argv0_to_fate, argv0, stat); - free(argv0); - htab_removeat_pid_str(&g_pid_to_argv0.h, bucket); + char *bundleid = bucket->value; + xxpc_dictionary_set_int64(g_bundleid_to_fate, bundleid, stat); + free(bundleid); + htab_removeat_pid_str(&g_pid_to_bundleid.h, bucket); +end: pthread_mutex_unlock(&g_dicts_lock); } @@ -473,16 +478,28 @@ int hook_xpc_pipe_try_receive(mach_port_t port_set, xxpc_object_t *requestp, return res; } xxpc_object_t reply = NULL; - if (!strcmp(name, "argv0-to-fate")) { - const char *argv0 = xxpc_dictionary_get_string(in, "argv0"); - if (!argv0) { + if (!strcmp(name, "bundleid-to-fate")) { + const char *bundleid = xxpc_dictionary_get_string(in, "bundleid"); + if (!bundleid) { ib_log("invalid hook-operation message"); return res; } reply = xxpc_dictionary_create_reply(request); - xxpc_object_t fate = xxpc_dictionary_get_value(g_argv0_to_fate, argv0); - if (fate) - xxpc_dictionary_set_value(reply, "out", fate); + xxpc_object_t out = xxpc_dictionary_create(NULL, NULL, 0); + xxpc_object_t fate = xxpc_dictionary_get_value(g_bundleid_to_fate, bundleid); + if (fate) { + if (IB_VERBOSE) { + char *desc = xxpc_copy_description(fate); + ib_log("your (%s) fate is %s", bundleid, desc); + free(desc); + } + xxpc_dictionary_set_value(out, "fate", fate); + } else { + if (IB_VERBOSE) + ib_log("your (%s) fate is unavailable", bundleid); + } + xxpc_dictionary_set_value(reply, "out", out); + xxpc_release(out); } else { ib_log("unknown hook-operation '%s'", name); return res; @@ -556,7 +573,7 @@ static void init() { * (it also decreases the amount of library code necessary to load from * disk...) */ - g_argv0_to_fate = xxpc_dictionary_create(NULL, NULL, 0); + g_bundleid_to_fate = xxpc_dictionary_create(NULL, NULL, 0); const char *image0 = _dyld_get_image_name(0); g_is_launchd = !!strstr(image0, "launchd"); diff --git a/darwin-bootstrap/substituted.m b/darwin-bootstrap/substituted.m index f03670c..2b25c17 100644 --- a/darwin-bootstrap/substituted.m +++ b/darwin-bootstrap/substituted.m @@ -200,40 +200,55 @@ enum convert_filters_ret { return PROVISIONAL_PASS; } -- (void)updateSpringBoardNeedsSafe:(const char *)argv0 then:(void (^)())then { +- (void)updateSpringBoardNeedsSafeThen:(void (^)())then { xxpc_object_t inn = xxpc_dictionary_create(NULL, NULL, 0); - xxpc_dictionary_set_string(inn, "com.ex.substiute.hook-operation", - "argv0-to-fate"); - xxpc_dictionary_set_string(inn, "argv0", argv0); + xxpc_dictionary_set_string(inn, "com.ex.substitute.hook-operation", + "bundleid-to-fate"); + xxpc_dictionary_set_string(inn, "bundleid", "com.apple.SpringBoard"); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + int to_set = REALLY_SAFE; xxpc_object_t out = NULL; vproc_swap_complex(NULL, 99999, inn, &out); - int to_set = REALLY_SAFE; if (!out) { NSLog(@"couldn't talk to launchd :( - assume worst case scenario"); goto out; } - if (xxpc_get_type(out) != XXPC_TYPE_INT64) { - NSLog(@"wrong type from launchd!?"); - goto out; + __unsafe_unretained xxpc_type_t type = xxpc_get_type(out); + if (xxpc_get_type(out) != XXPC_TYPE_DICTIONARY) + goto bad_data; + + bool crashed; + __unsafe_unretained xxpc_object_t fate = + xxpc_dictionary_get_value(out, "fate"); + if (!fate) { + /* no record yet */ + crashed = false; + } else if (xxpc_get_type(out) == XXPC_TYPE_INT64) { + int stat = (int) xxpc_int64_get_value(out); + crashed = WIFSIGNALED(stat) && WTERMSIG(stat) != SIGTERM; + } else { + goto bad_data; } - int stat = (int) xxpc_int64_get_value(out); - bool crashed = WIFSIGNALED(stat) && WTERMSIG(stat) != SIGTERM; + if (crashed) { if (g_springboard_needs_safe) { - NSLog(@"SpringBoard hung up more than once without without saying bye; using Really Safe Mode (no UI) next time :("); + NSLog(@"SpringBoard crashed while in safe mode; using Really Safe Mode (no UI) next time :("); to_set = REALLY_SAFE; } else { - NSLog(@"SpringBoard hung up without saying bye; using safe mode next time."); + NSLog(@"SpringBoard crashed; using safe mode next time."); to_set = NEEDS_SAFE; } } else { to_set = NO_SAFE; } + goto out; + bad_data: + NSLog(@"bad data %@ from launchd!?", out); + goto out; out: dispatch_async(dispatch_get_main_queue(), ^{ g_springboard_needs_safe = to_set; @@ -258,8 +273,9 @@ enum convert_filters_ret { _is_springboard = [_argv0 isEqualToString:sb_exe]; if (_is_springboard) - [self updateSpringBoardNeedsSafe:argv0 - then:^{[self handleMessageHelloRest:request];}]; + [self updateSpringBoardNeedsSafeThen:^{ + [self handleMessageHelloRest:request]; + }]; else [self handleMessageHelloRest:request]; return; diff --git a/lib/darwin/xxpc.h b/lib/darwin/xxpc.h index 4b5e175..7df28f6 100644 --- a/lib/darwin/xxpc.h +++ b/lib/darwin/xxpc.h @@ -20,6 +20,7 @@ typedef void (^xxpc_handler_t)(xxpc_object_t); static const xxpc_object_t name = DC_CAST &x_##name DEFINE_CONST(XXPC_TYPE_CONNECTION, _xpc_type_connection); +DEFINE_CONST(XXPC_TYPE_BOOL, _xpc_type_error); DEFINE_CONST(XXPC_TYPE_ERROR, _xpc_type_error); DEFINE_CONST(XXPC_TYPE_DICTIONARY, _xpc_type_dictionary); DEFINE_CONST(XXPC_TYPE_ARRAY, _xpc_type_array); @@ -43,6 +44,9 @@ xxpc_object_t WRAP(xpc_retain, (xxpc_object_t)); #endif char *WRAP(xpc_copy_description, (xxpc_object_t)); +#if OS_OBJECT_USE_OBJC +__attribute__((ns_returns_autoreleased)) +#endif xxpc_type_t WRAP(xpc_get_type, (xxpc_object_t)); xxpc_object_t WRAP(xpc_string_create, (const char *)); const char *WRAP(xpc_string_get_string_ptr, (xxpc_object_t)); diff --git a/script/gen-deb.sh b/script/gen-deb.sh index 999765c..5a0d599 100755 --- a/script/gen-deb.sh +++ b/script/gen-deb.sh @@ -14,7 +14,7 @@ mkdir -p $debroot/usr/include/substitute cp lib/substitute.h $debroot/usr/include/substitute/ cp substrate/substrate.h $debroot/usr/include/substitute/ mkdir -p $debroot/Library/Substitute/DynamicLibraries -cp darwin-bootstrap/safemode-ui-hook.plist out/safemode-ui-hook.dylib $debroot/Library/Substitute/DynamicLibraries/ +#cp darwin-bootstrap/safemode-ui-hook.plist out/safemode-ui-hook.dylib $debroot/Library/Substitute/DynamicLibraries/ mkdir -p $debroot/Library/Substitute/Helpers cp out/{posixspawn-hook.dylib,bundle-loader.dylib,unrestrict,inject-into-launchd,substituted} $debroot/Library/Substitute/Helpers/ mkdir -p $debroot/etc/rc.d diff --git a/test/test-htab.c b/test/test-htab.c index 9be59a3..c85d620 100644 --- a/test/test-htab.c +++ b/test/test-htab.c @@ -30,8 +30,8 @@ int main() { struct htab_teststr_int *hp; - HTAB_STORAGE(teststr_int) stor; - HTAB_STORAGE_INIT(&stor, teststr_int); + HTAB_STORAGE(teststr_int) stor = HTAB_STORAGE_INIT_STATIC(&stor, teststr_int); + /*HTAB_STORAGE_INIT(&stor, teststr_int);*/ hp = &stor.h; for(int i = 0; i < 100; i++) { const char *k; @@ -39,6 +39,8 @@ int main() { bool new; *htab_setp_teststr_int(hp, &k, &new) = i; assert(new); + assert(htab_getbucket_teststr_int(hp, &k)->value == i); + assert(*htab_getp_teststr_int(hp, &k) == i); } { const char *k = "foo31"; |