diff options
author | comex | 2015-02-28 13:16:36 -0500 |
---|---|---|
committer | comex | 2015-02-28 13:16:36 -0500 |
commit | d9a7a8a4d4a23fb65e6319e0e8a435046cc39fea (patch) | |
tree | dd219509fc92e695317b82d5dca43296daaf2ab1 /ios-bootstrap | |
parent | remove deprecated property usage in safety-dance (diff) | |
download | substitute-d9a7a8a4d4a23fb65e6319e0e8a435046cc39fea.tar.gz |
Rename ios-bootstrap to darwin-bootstrap; cleanup posixspawn-hook and unrestrict.
Not tested yet.
Diffstat (limited to 'ios-bootstrap')
-rw-r--r-- | ios-bootstrap/bundle-loader.m | 161 | ||||
-rw-r--r-- | ios-bootstrap/ib-log.h | 27 | ||||
-rw-r--r-- | ios-bootstrap/inject-into-launchd.c | 90 | ||||
-rw-r--r-- | ios-bootstrap/posixspawn-hook.c | 352 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/AutoGrid.h | 17 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/AutoGrid.m | 106 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/Info.plist | 88 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/main.m | 159 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/white.png | bin | 1047 -> 0 bytes | |||
-rw-r--r-- | ios-bootstrap/unrestrict.c | 115 |
10 files changed, 0 insertions, 1115 deletions
diff --git a/ios-bootstrap/bundle-loader.m b/ios-bootstrap/bundle-loader.m deleted file mode 100644 index fec2513..0000000 --- a/ios-bootstrap/bundle-loader.m +++ /dev/null @@ -1,161 +0,0 @@ -#import <Foundation/Foundation.h> -#import <CoreFoundation/CoreFoundation.h> -#include <dlfcn.h> -extern char ***_NSGetArgv(void); - -#define PREFIX "Substitute bundle loader: " - -enum test_filters_ret { - PASSED, - FAILED, - INVALID -}; - -static double id_to_double(id o) { - if ([o isKindOfClass:[NSString class]]) { - NSScanner *scan = [NSScanner scannerWithString:o]; - double d; - if (![scan scanDouble:&d] || !scan.atEnd) - return NAN; - return d; - } else if ([o isKindOfClass:[NSNumber class]]) { - return [o doubleValue]; - } else { - return NAN; - } -} - -static enum test_filters_ret test_filters(NSDictionary *plist_dict) { - - NSDictionary *filter = [plist_dict objectForKey:@"Filter"]; - if (!filter) - return PASSED; - if (![filter isKindOfClass:[NSDictionary class]]) - return INVALID; - - for (NSString *key in [filter allKeys]) { - if (!([key isEqualToString:@"CoreFoundationVersion"] || - [key isEqualToString:@"Classes"] || - [key isEqualToString:@"Bundles"] || - [key isEqualToString:@"Executables"])) { - return INVALID; - } - } - NSArray *cfv = [filter objectForKey:@"CoreFoundationVersion"]; - if (cfv) { - if (![cfv isKindOfClass:[NSArray class]] || - [cfv count] == 0 || - [cfv count] > 2) - return INVALID; - double version = kCFCoreFoundationVersionNumber; - double minimum = id_to_double([cfv objectAtIndex:0]); - if (minimum != minimum) - return INVALID; - if (version < minimum) - return FAILED; - id supremum_o = [cfv objectAtIndex:1]; - if (supremum_o) { - double supremum = id_to_double(supremum_o); - if (supremum != supremum) - return INVALID; - if (version >= supremum) - return FAILED; - } - } - - NSArray *classes = [filter objectForKey:@"Classes"]; - if (classes) { - if (![classes isKindOfClass:[NSArray class]]) - return INVALID; - for (NSString *name in classes) { - if (![name isKindOfClass:[NSString class]]) - return INVALID; - if (NSClassFromString(name)) - goto ok1; - } - return FAILED; - ok1:; - } - - NSArray *bundles = [filter objectForKey:@"Bundles"]; - if (bundles) { - if (![bundles isKindOfClass:[NSArray class]]) - return INVALID; - for (NSString *identifier in bundles) { - if (![identifier isKindOfClass:[NSString class]]) - return INVALID; - if ([NSBundle bundleWithIdentifier:identifier]) - goto ok2; - } - return FAILED; - ok2:; - } - - - NSArray *executables = [filter objectForKey:@"Executables"]; - if (executables) { - const char *argv0 = (*_NSGetArgv())[0]; - NSString *exe = nil; - if (argv0) { - NSString *nsargv0 = [NSString stringWithCString:argv0 - encoding:NSUTF8StringEncoding]; - exe = [[nsargv0 pathComponents] lastObject]; - } - if (!exe) - exe = @""; - if (![executables isKindOfClass:[NSArray class]]) - return INVALID; - for (NSString *name in executables) { - if (![name isKindOfClass:[NSString class]]) - return INVALID; - if ([name isEqualToString:exe]) - goto ok3; - } - return FAILED; - ok3:; - } - return PASSED; -} - -/* this is DYLD_INSERT_LIBRARIES'd, not injected. */ -__attribute__((constructor)) -static void init() { - NSError *err; - NSString *base = @"/Library/Substitute/DynamicLibraries"; - NSArray *list = [[NSFileManager defaultManager] - contentsOfDirectoryAtPath:base - error:&err]; - if (!list) - return; - - for (NSString *dylib in list) { - if (![[dylib pathExtension] isEqualToString:@"dylib"]) - continue; - NSString *plist = [[dylib stringByDeletingPathExtension] - stringByAppendingPathExtension:@"plist"]; - NSString *full_plist = [base stringByAppendingPathComponent:plist]; - NSDictionary *plist_dict = [NSDictionary dictionaryWithContentsOfFile: - full_plist]; - if (!plist_dict) { - NSLog(@PREFIX "missing, unreadable, or invalid plist '%@' for dylib '%@'; unlike Substrate, we require plists", full_plist, dylib); - continue; - } - enum test_filters_ret ret = test_filters(plist_dict); - if (ret == FAILED) { - continue; - } else if (ret == INVALID) { - NSLog(@PREFIX "bad data in plist '%@' for dylib '%@'", full_plist, dylib); - continue; - } - NSString *full_dylib = [base stringByAppendingPathComponent:dylib]; - const char *c_dylib = [full_dylib cStringUsingEncoding:NSUTF8StringEncoding]; - if (!c_dylib) { - NSLog(@PREFIX "Not loading weird dylib path %@", full_dylib); - continue; - } - NSLog(@"Substitute loading %@", full_dylib); - if (!dlopen(c_dylib, RTLD_LAZY)) { - NSLog(@PREFIX "Failed to load %@: %s", full_dylib, dlerror()); - } - } -} diff --git a/ios-bootstrap/ib-log.h b/ios-bootstrap/ib-log.h deleted file mode 100644 index fee70b5..0000000 --- a/ios-bootstrap/ib-log.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include <dispatch/dispatch.h> -#include <stdio.h> -#include <unistd.h> - -static FILE *logfp; -static void open_logfp_if_necessary() { - /* syslog() doesn't seem to work from launchd... */ - static dispatch_once_t pred; - dispatch_once(&pred, ^{ - char filename[128]; - sprintf(filename, "/tmp/substitute-" IB_LOG_NAME "-log.%ld", - (long) getpid()); - logfp = fopen(filename, "w"); - if (!logfp) { - /* Ack... */ - logfp = stderr; - } - }); -} -#define ib_log(fmt, args...) do { \ - open_logfp_if_necessary(); \ - fprintf(logfp, fmt "\n", ##args); \ - fflush(logfp); \ -} while(0) - -#define IB_VERBOSE 0 diff --git a/ios-bootstrap/inject-into-launchd.c b/ios-bootstrap/inject-into-launchd.c deleted file mode 100644 index 4396f14..0000000 --- a/ios-bootstrap/inject-into-launchd.c +++ /dev/null @@ -1,90 +0,0 @@ -#define IB_LOG_NAME "iil" -#include "ib-log.h" -#include "substitute.h" -#include "substitute-internal.h" -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <stdbool.h> -#include <stdint.h> -#include <syslog.h> -#include <CoreFoundation/CoreFoundation.h> - -void *IOHIDEventCreateKeyboardEvent(CFAllocatorRef, uint64_t, uint32_t, uint32_t, bool, uint32_t); -void *IOHIDEventSystemCreate(CFAllocatorRef); -void *IOHIDEventSystemCopyEvent(void *, uint32_t, void *, uint32_t); - -CFIndex IOHIDEventGetIntegerValue(void *, uint32_t); -enum { - kIOHIDEventTypeKeyboard = 3, - kIOHIDEventFieldKeyboardDown = 3 << 16 | 2, -}; - -static bool button_pressed(void *event_system, uint32_t usage_page, uint32_t usage) { - /* This magic comes straight from Substrate... I don't really understand - * what it's doing. In particular, where is the equivalent kernel - * implementation on OS X? Does it not exist? But I guess Substrate is - * emulating backboardd. */ - void *dummy = IOHIDEventCreateKeyboardEvent(NULL, mach_absolute_time(), - usage_page, usage, - 0, 0); - if (!dummy) { - ib_log("couldn't create dummy HID event"); - return false; - } - void *event = IOHIDEventSystemCopyEvent(event_system, - kIOHIDEventTypeKeyboard, - dummy, 0); - if (!event) - return false; - CFIndex ival = IOHIDEventGetIntegerValue(event, kIOHIDEventFieldKeyboardDown); - return ival; -} - -int main(UNUSED int argc, char **argv) { - pid_t pid = argv[1] ? atoi(argv[1]) : 1; /* for testing */ - - void *event_system = IOHIDEventSystemCreate(NULL); - if (!event_system) { - ib_log("couldn't create HID event system"); - } else { - - /* consumer page -> Volume Increment */ - if (button_pressed(event_system, 0x0c, 0xe9) || - /* telephony page -> Flash */ - button_pressed(event_system, 0x0b, 0x21)) { - ib_log("disabling due to button press"); - return 0; - } - } - mach_port_t port = 0; - kern_return_t kr = mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - &port); - if (kr) { - ib_log("mach_port_allocate: %x", kr); - return 0; - } - const char *lib = "/Library/Substitute/posixspawn-hook.dylib"; - struct shuttle shuttle = { - .type = SUBSTITUTE_SHUTTLE_MACH_PORT, - .u.mach.right_type = MACH_MSG_TYPE_MAKE_SEND, - .u.mach.port = port - }; - char *error; - int ret = substitute_dlopen_in_pid(pid, lib, 0, &shuttle, 1, &error); - if (ret) { - ib_log("substitute_dlopen_in_pid: %s/%s", - substitute_strerror(ret), error); - return 0; - } - /* wait for it to finish */ - static struct { - mach_msg_header_t hdr; - mach_msg_trailer_t huh; - } msg; - kr = mach_msg_overwrite(NULL, MACH_RCV_MSG, 0, sizeof(msg), port, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL, - &msg.hdr, 0); - if (kr) - ib_log("mach_msg_overwrite: %x", kr); -} diff --git a/ios-bootstrap/posixspawn-hook.c b/ios-bootstrap/posixspawn-hook.c deleted file mode 100644 index 80339e1..0000000 --- a/ios-bootstrap/posixspawn-hook.c +++ /dev/null @@ -1,352 +0,0 @@ -#define IB_LOG_NAME "posixspawn-hook" -#include "ib-log.h" -#include "substitute.h" -#include "substitute-internal.h" -#include <mach/mach.h> -#include <mach-o/dyld.h> -#include <spawn.h> -#include <sys/wait.h> -#include <syslog.h> -#include <malloc/malloc.h> -#include <assert.h> -#include <errno.h> - -extern char ***_NSGetEnviron(void); - -static __typeof__(posix_spawn) *old_posix_spawn, *old_posix_spawnp, - hook_posix_spawn, hook_posix_spawnp; -static __typeof__(wait4) *old_wait4, hook_wait4; -static __typeof__(waitpid) *old_waitpid, hook_waitpid; - -static bool advance(char **strp, const char *template) { - size_t len = strlen(template); - if (!strncmp(*strp, template, len)) { - *strp += len; - return true; - } - return false; -} - -static bool spawn_unrestrict(pid_t pid, bool should_resume, bool is_exec) { - const char *prog = "/Library/Substitute/unrestrict"; - char pid_s[32]; - sprintf(pid_s, "%ld", (long) pid); - const char *should_resume_s = should_resume ? "1" : "0"; - const char *is_exec_s = is_exec ? "1" : "0"; - const char *argv[] = {prog, pid_s, should_resume_s, is_exec_s, NULL}; - pid_t prog_pid; - if (old_posix_spawn(&prog_pid, prog, NULL, NULL, (char **) argv, NULL)) { - ib_log("posixspawn-hook: couldn't start unrestrict - oh well..."); - return false; - } - int xstat; - /* reap intermediate to avoid zombie - if it doesn't work, not a big deal */ - if (waitpid(prog_pid, &xstat, 0) == -1) - ib_log("posixspawn-hook: couldn't waitpid"); - ib_log("unrestrict xstat=%x", xstat); - return true; -} - -static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old, - pid_t *restrict pidp, const char *restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], - char *const envp[restrict]) { - char *new = NULL; - char **new_envp = NULL; - char *const *envp_to_use = envp; - char *const *my_envp = envp ? envp : *_NSGetEnviron(); - posix_spawnattr_t my_attr = NULL; - - if (attrp) { - posix_spawnattr_t attr = *attrp; - size_t size = malloc_size(attr); - my_attr = malloc(size); - if (!my_attr) - goto crap; - memcpy(my_attr, attr, size); - } else { - if (posix_spawnattr_init(&my_attr)) - goto crap; - } - - short flags; - if (posix_spawnattr_getflags(&my_attr, &flags)) - goto crap; - if (IB_VERBOSE) { - ib_log("hook_posix_spawn_generic: path=%s%s%s", - path, - (flags & POSIX_SPAWN_SETEXEC) ? " (exec)" : "", - (flags & POSIX_SPAWN_START_SUSPENDED) ? " (suspend)" : ""); - for (char *const *ap = argv; *ap; ap++) - ib_log(" %s", *ap); - } - - /* This mirrors Substrate's logic with safe mode. I don't really - * understand the point of the difference between its 'safe' (which removes - * Substrate from DYLD_INSERT_LIBRARIES) and 'quit' (which just skips - * directly to the original spawn), but I guess I'll just do the same for - * maximum safety... */ - bool safe_mode = false; - - /* If Foundation is loaded into notifyd, the system doesn't boot. I spent - * some time trying to figure out why, but managed to brick my device - * instead (no idea how that happened either). I want to solve this before - * a stable release, but this works for now. - * n.b. Substrate isn't affected by this because it uses only - * CoreFoundation, not Foundation. However, CoreFoundation is pretty big - * itself, and also brings in libobjc, so it's not necessarily that - * principled to switch. I suppose principled might be to extract the - * plist code from CF... */ - if (!strcmp(path, "/usr/sbin/notifyd")) { - /* why? */ - safe_mode = true; - } - - - const char *orig_dyld_insert = ""; - static const char my_dylib_1[] = - "/Library/Substitute/bundle-loader.dylib"; - static const char my_dylib_2[] = - "/Library/Substitute/posixspawn-hook.dylib"; - size_t env_count = 0; - for (char *const *ep = my_envp; *ep; ep++) { - env_count++; - char *env = *ep; - if (advance(&env, "_MSSafeMode=") || advance(&env, "_SubstituteSafeMode=")) { - if (!strcmp(env, "0") || !strcmp(env, "NO")) - continue; - else if (!strcmp(env, "1") || !strcmp(env, "YES")) - safe_mode = true; - else - goto skip; - } else if (advance(&env, "DYLD_INSERT_LIBRARIES=")) { - orig_dyld_insert = env; - } - } - new = malloc(sizeof("DYLD_INSERT_LIBRARIES=") - 1 + - sizeof(my_dylib_2) /* not - 1, because : */ + - strlen(orig_dyld_insert) + 1); - char *newp_orig = stpcpy(new, "DYLD_INSERT_LIBRARIES="); - char *newp = newp_orig; - const char *p = orig_dyld_insert; - while (*p) { /* W.N.H. */ - const char *next = strchr(p, ':') ?: (p + strlen(p)); - /* append if it isn't one of ours */ - bool is_substitute = - (next - p == sizeof(my_dylib_1) - 1 && - !memcmp(next, my_dylib_1, sizeof(my_dylib_1) - 1)) || - (next - p == sizeof(my_dylib_2) - 1 && - !memcmp(next, my_dylib_2, sizeof(my_dylib_2) - 1)); - if (!is_substitute) { - if (newp != newp_orig) - *newp++ = ':'; - memcpy(newp, p, next - p); - newp += next - p; - } - if (!*next) - break; - p = next + 1; - } - /* append ours if necessary */ - if (!safe_mode) { - if (newp != newp_orig) - *newp++ = ':'; - const char *dylib_to_add = !strcmp(path, "/usr/libexec/xpcproxy") - ? my_dylib_2 - : my_dylib_1; - newp = stpcpy(newp, dylib_to_add); - } - if (IB_VERBOSE) - ib_log("using %s", new); - /* no libraries? then just get rid of it */ - if (newp == newp_orig) { - free(new); - new = NULL; - } - new_envp = malloc(sizeof(char *) * (env_count + 2)); - envp_to_use = new_envp; - char **outp = new_envp; - for (size_t idx = 0; idx < env_count; idx++) { - char *env = my_envp[idx]; - /* remove *all* D_I_L, including duplicates */ - if (!advance(&env, "DYLD_INSERT_LIBRARIES=")) - *outp++ = env; - } - if (new) - *outp++ = new; - *outp++ = NULL; - - if (safe_mode) - goto skip; - - - /* XXX Even async on a separate thread, task_for_pid from launchd hangs in - * kernel - AMFI permitUnrestrictedDebugging waiting on some mach port. - * Normally (from other processes) task_for_pid doesn't even ask amfid - * because we have the right entitlements, but it doesn't usually *hang*. - * Probably should do what Substrate does and only launch a process for the - * few actually restricted executables. I was originally hesitant about - * this because of complications with fat files. Whatever. */ - bool need_unrestrict = getuid() == 0; - - /* Deal with the dumb __restrict section. A complication is that this - * could actually be an exec. */ - /* TODO skip this if Substrate is doing it anyway */ - bool was_suspended; - if (need_unrestrict) { - was_suspended = flags & POSIX_SPAWN_START_SUSPENDED; - flags |= POSIX_SPAWN_START_SUSPENDED; - if (posix_spawnattr_setflags(&my_attr, flags)) - goto crap; - if (flags & POSIX_SPAWN_SETEXEC) { - /* make the marker fd; hope you weren't using that */ - if (dup2(2, 255) != 255) { - ib_log("dup2 failure - %s", strerror(errno)); - goto skip; - } - if (fcntl(255, F_SETFD, FD_CLOEXEC)) - goto crap; - if (IB_VERBOSE) - ib_log("spawning unrestrict"); - if (!spawn_unrestrict(getpid(), !was_suspended, true)) - goto skip; - } - } - if (IB_VERBOSE) - ib_log("**"); - int ret = old(pidp, path, file_actions, &my_attr, argv, envp_to_use); - if (IB_VERBOSE) - ib_log("ret=%d pid=%ld", ret, (long) *pidp); - if (ret) - goto cleanup; - /* Since it returned, obviously it was not SETEXEC, so we need to - * unrestrict it ourself. */ - pid_t pid = *pidp; -#if 0 - dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, - 0); - dispatch_async(q, ^{ - char *error; - ib_log("unrestricting %d", pid); - int sret = substitute_ios_unrestrict(pid, !was_suspended, &error); - ib_log("unrestricting done"); - if (sret) { - ib_log("posixspawn-hook: substitute_ios_unrestrict => %d (%s)", - sret, error); - } - free(error); - }); -#else - if (need_unrestrict) - spawn_unrestrict(pid, !was_suspended, false); -#endif - goto cleanup; -crap: - ib_log("posixspawn-hook: weird error - OOM? skipping our stuff"); -skip: - ret = old(pidp, path, file_actions, attrp, argv, envp); -cleanup: - free(new_envp); - free(new); - free(my_attr); - return ret; -} - -static void after_wait_generic(pid_t pid, int stat) { - /* TODO safety */ - (void) pid; - (void) stat; -} - -int hook_posix_spawn(pid_t *restrict pid, const char *restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], char *const envp[restrict]) { - return hook_posix_spawn_generic(old_posix_spawn, pid, path, file_actions, - attrp, argv, envp); -} - -int hook_posix_spawnp(pid_t *restrict pid, const char *restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], char *const envp[restrict]) { - return hook_posix_spawn_generic(old_posix_spawnp, pid, path, file_actions, - attrp, argv, envp); -} - -pid_t hook_wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage) { - pid_t ret = old_wait4(pid, stat_loc, options, rusage); - after_wait_generic(ret, *stat_loc); - return ret; -} - -pid_t hook_waitpid(pid_t pid, int *stat_loc, int options) { - pid_t ret = old_waitpid(pid, stat_loc, options); - after_wait_generic(ret, *stat_loc); - return ret; -} - -void substitute_init(struct shuttle *shuttle, size_t nshuttle) { - /* Just tell them we're done */ - if (nshuttle != 1) { - ib_log("nshuttle = %zd?", nshuttle); - return; - } - mach_port_t notify_port = shuttle[0].u.mach.port; - mach_msg_header_t done_hdr; - done_hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, 0); - done_hdr.msgh_size = sizeof(done_hdr); - done_hdr.msgh_remote_port = notify_port; - done_hdr.msgh_local_port = 0; - done_hdr.msgh_voucher_port = 0; - done_hdr.msgh_id = 42; - kern_return_t kr = mach_msg_send(&done_hdr); - if (kr) - ib_log("posixspawn-hook: mach_msg_send failed: kr=%x", kr); - /* MOVE deallocated the port */ -} - -__attribute__((constructor)) -static void init() { - /* Note: I'm using interposing to minimize the chance of conflict with - * Substrate. This shouldn't actually be necessary, because MSHookProcess, - * at least as of the old version I'm looking at the source code of, blocks - * until the thread it remotely creates exits, and that thread does - * pthread_join on the 'real' pthread it creates to do the dlopen (unlike - * the equivalent in Substitute - the difference is to decrease dependence - * on pthread internals). substitute_dlopen_in_pid does not, but that's - * what the notify port is for. Meanwhile, the jailbreak I have installed - * properly runs rc.d sequentially, so the injection tools won't do their - * thing at the same time. But just in case any of that doesn't hold up... - * - * (it also decreases the amount of library code necessary to load from - * disk...) - */ - - struct substitute_image *im = substitute_open_image(_dyld_get_image_name(0)); - if (!im) { - ib_log("posixspawn-hook: substitute_open_image failed"); - goto end; - } - - static const struct substitute_import_hook hooks[] = { - {"_posix_spawn", hook_posix_spawn, &old_posix_spawn}, - {"_posix_spawnp", hook_posix_spawnp, &old_posix_spawnp}, - {"_waitpid", hook_waitpid, &old_waitpid}, - {"_wait4", hook_wait4, &old_wait4}, - }; - - int err = substitute_interpose_imports(im, hooks, sizeof(hooks)/sizeof(*hooks), 0); - if (err) { - ib_log("posixspawn-hook: substitute_interpose_imports failed: %s", - substitute_strerror(err)); - goto end; - } - -end: - if (im) - substitute_close_image(im); - -} diff --git a/ios-bootstrap/safety-dance/AutoGrid.h b/ios-bootstrap/safety-dance/AutoGrid.h deleted file mode 100644 index 335381a..0000000 --- a/ios-bootstrap/safety-dance/AutoGrid.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// AutoGrid.h -// SafetyDance -// -// Created by Nicholas Allegra on 1/26/15. -// Copyright (c) 2015 Nicholas Allegra. All rights reserved. -// - -#import <UIKit/UIKit.h> - -@interface AutoGrid : UIView { - NSArray *views; - UIScrollView *scrollView; -} -- (void)setViews:(NSArray *)views; - -@end diff --git a/ios-bootstrap/safety-dance/AutoGrid.m b/ios-bootstrap/safety-dance/AutoGrid.m deleted file mode 100644 index 2a8d3ed..0000000 --- a/ios-bootstrap/safety-dance/AutoGrid.m +++ /dev/null @@ -1,106 +0,0 @@ -// -// AutoGrid.m -// SafetyDance -// -// Created by Nicholas Allegra on 1/26/15. -// Copyright (c) 2015 Nicholas Allegra. All rights reserved. -// - -#import "AutoGrid.h" - -@implementation AutoGrid -- (void)setViews:(NSArray *)_views { - views = _views; - [scrollView removeFromSuperview]; - scrollView = [[UIScrollView alloc] init]; - [self addSubview:scrollView]; - for (UIView *view in views) - [scrollView addSubview:view]; - [self setNeedsLayout]; -} - -- (void)layoutSubviews { - scrollView.frame = self.bounds; - CGFloat paddingX = 22, paddingY = 10; - NSUInteger nviews = [views count]; - CGSize *sizes = malloc(sizeof(*sizes) * nviews); - - for (NSUInteger i = 0; i < nviews; i++) - sizes[i] = [[views objectAtIndex:i] intrinsicContentSize]; - - CGFloat availableWidth = self.bounds.size.width; - /* try to lay out using an increasing number of columns */ - NSUInteger cols; - CGSize contentSize; - CGFloat *colWidths = NULL; - for (cols = 1; ; cols++) { - free(colWidths); - colWidths = malloc(sizeof(*colWidths) * cols); - for (NSUInteger col = 0; col < cols; col++) - colWidths[col] = 0; - CGFloat tentativeHeight = 0; - CGFloat tentativeWidth = 0; - for (NSUInteger row = 0; row < nviews / cols; row++) { - CGFloat totalWidth = 0; - CGFloat maxHeight = 0; - for (NSUInteger col = 0; col < cols; col++) { - NSUInteger i = row * cols + col; - if (i >= nviews) - goto done1; - CGSize size = sizes[i]; - if (size.width > colWidths[col]) - colWidths[col] = size.width; - if (col != 0) - totalWidth += paddingX; - totalWidth += size.width; - if (size.height > maxHeight) - maxHeight = size.height; - } - if (totalWidth > tentativeWidth) - tentativeWidth = totalWidth; - tentativeHeight += maxHeight + paddingY; - } - done1: - if (cols > 1 && tentativeWidth > availableWidth) { - cols--; - break; - } - contentSize = CGSizeMake(tentativeWidth, tentativeHeight); - NSLog(@"%f", contentSize.height); - if (contentSize.width == 0) - break; - - } - scrollView.contentSize = contentSize; - CGFloat y = 0; - for (NSUInteger row = 0; ; row++) { - CGFloat x = 0; - CGFloat maxHeight = 0; - for (NSUInteger col = 0; col < cols; col++) { - NSUInteger i = row * cols + col; - if (i >= nviews) - goto done2; - CGSize size = sizes[i]; - UIView *view = [views objectAtIndex:i]; - if (col != 0) - x += paddingX; - view.frame = CGRectMake(x, y, size.width, size.height); - x += colWidths[col]; - if (size.height > maxHeight) - maxHeight = size.height; - } - y += maxHeight + paddingY; - } -done2: - free(sizes); - free(colWidths); -} -/* -// Only override drawRect: if you perform custom drawing. -// An empty implementation adversely affects performance during animation. -- (void)drawRect:(CGRect)rect { - // Drawing code -} -*/ - -@end diff --git a/ios-bootstrap/safety-dance/Info.plist b/ios-bootstrap/safety-dance/Info.plist deleted file mode 100644 index f2fa520..0000000 --- a/ios-bootstrap/safety-dance/Info.plist +++ /dev/null @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>en</string> - <key>CFBundleExecutable</key> - <string>SafetyDance</string> - <key>CFBundleIdentifier</key> - <string>com.ex.SafetyDance</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>SafetyDance</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleShortVersionString</key> - <string>1.0</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleVersion</key> - <string>1</string> - <key>LSRequiresIPhoneOS</key> - <false/> - <key>UILaunchImages</key> - <array> - <dict> - <key>UILaunchImageMinimumOSVersion</key> - <string>7.0</string> - <key>UILaunchImageName</key> - <string>Default</string> - <key>UILaunchImageOrientation</key> - <string>Portrait</string> - <key>UILaunchImageSize</key> - <string>{320, 480}</string> - </dict> - <dict> - <key>UILaunchImageMinimumOSVersion</key> - <string>7.0</string> - <key>UILaunchImageName</key> - <string>Default</string> - <key>UILaunchImageOrientation</key> - <string>Portrait</string> - <key>UILaunchImageSize</key> - <string>{320, 568}</string> - </dict> - <dict> - <key>UILaunchImageMinimumOSVersion</key> - <string>8.0</string> - <key>UILaunchImageName</key> - <string>Default</string> - <key>UILaunchImageOrientation</key> - <string>Portrait</string> - <key>UILaunchImageSize</key> - <string>{375, 667}</string> - </dict> - <dict> - <key>UILaunchImageMinimumOSVersion</key> - <string>8.0</string> - <key>UILaunchImageName</key> - <string>Default</string> - <key>UILaunchImageOrientation</key> - <string>Portrait</string> - <key>UILaunchImageSize</key> - <string>{414, 736}</string> - </dict> - <dict> - <key>UILaunchImageMinimumOSVersion</key> - <string>7.0</string> - <key>UILaunchImageName</key> - <string>Default</string> - <key>UILaunchImageOrientation</key> - <string>Portrait</string> - <key>UILaunchImageSize</key> - <string>{768, 1024}</string> - </dict> - </array> - <key>UIStatusBarStyle</key> - <string>UIStatusBarStyleLightContent</string> - <key>UISupportedInterfaceOrientations</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> -</dict> -</plist> diff --git a/ios-bootstrap/safety-dance/main.m b/ios-bootstrap/safety-dance/main.m deleted file mode 100644 index 0d05e00..0000000 --- a/ios-bootstrap/safety-dance/main.m +++ /dev/null @@ -1,159 +0,0 @@ -#import <UIKit/UIKit.h> -#import "AutoGrid.h" - -@interface ViewController : UIViewController { - AutoGrid *autoGrid; -} - -@end - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - [self loadStuff]; - NSMutableArray *names = [NSMutableArray array]; - for (int i = 0; i < 100; i++) - [names addObject:[NSString stringWithFormat:@"Some Dylib %d", i]]; - NSMutableArray *views = [NSMutableArray array]; - for (NSString *name in names) { - UILabel *label = [[UILabel alloc] init]; - label.text = name; - [views addObject:label]; - } - [autoGrid setViews:views]; -} - -#define EXPLANATION \ - @"SpringBoard seems to have crashed. The cause might be a Substitute jailbreak extension, or unrelated. Just to be safe, extensions in SpringBoard have been temporarily disabled. You can continue in this mode, or restart SpringBoard normally.\n\nThe following extensions were running:" - -static void hugging(UIView *view, UILayoutPriority pri) { - [view setContentHuggingPriority:pri forAxis:UILayoutConstraintAxisHorizontal]; - [view setContentHuggingPriority:pri forAxis:UILayoutConstraintAxisVertical]; -} -static void compression(UIView *view, UILayoutPriority pri) { - [view setContentCompressionResistancePriority:pri forAxis:UILayoutConstraintAxisHorizontal]; - [view setContentCompressionResistancePriority:pri forAxis:UILayoutConstraintAxisVertical]; -} - -- (void)loadStuff { - self.view.backgroundColor = [UIColor whiteColor]; - - UILabel *top = [[UILabel alloc] init]; - top.translatesAutoresizingMaskIntoConstraints = NO; - top.textAlignment = NSTextAlignmentCenter; - hugging(top, 251); - top.text = @"libsubstitute"; - top.font = [UIFont systemFontOfSize:23]; - [self.view addSubview:top]; - - UILabel *big = [[UILabel alloc] init]; - big.translatesAutoresizingMaskIntoConstraints = NO; - big.textAlignment = NSTextAlignmentCenter; - hugging(big, 251); - [big setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisHorizontal]; - [big setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisVertical]; - big.text = @"Safe Mode"; - big.font = [UIFont systemFontOfSize:32]; - [self.view addSubview:big]; - - UILabel *explain = [[UILabel alloc] init]; - explain.translatesAutoresizingMaskIntoConstraints = NO; - explain.textAlignment = NSTextAlignmentCenter; - hugging(explain, 251); - compression(explain, 999); - explain.text = EXPLANATION; - explain.font = [UIFont systemFontOfSize:14]; - explain.minimumScaleFactor = 0.5; /* test */ - explain.numberOfLines = 0; - [self.view addSubview:explain]; - - UIButton *returnButton = [UIButton buttonWithType:UIButtonTypeSystem]; - returnButton.translatesAutoresizingMaskIntoConstraints = NO; - returnButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; - returnButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; - returnButton.titleLabel.font = [UIFont systemFontOfSize:17]; - [returnButton setTitle:@"Return to Normal" forState:UIControlStateNormal]; - [self.view addSubview:returnButton]; - - UIButton *continueButton = [UIButton buttonWithType:UIButtonTypeSystem]; - continueButton.translatesAutoresizingMaskIntoConstraints = NO; - hugging(continueButton, 999); - compression(continueButton, 300); - continueButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; - continueButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; - continueButton.titleLabel.font = [UIFont systemFontOfSize:17]; - [continueButton setTitle:@"Continue in Safe Mode" forState:UIControlStateNormal]; - [self.view addSubview:continueButton]; - - autoGrid = [[AutoGrid alloc] init]; - autoGrid.translatesAutoresizingMaskIntoConstraints = NO; - [self.view addSubview:autoGrid]; - - NSDictionary *viewsDictionary = @{ - @"top": top, - @"big": big, - @"explain": explain, - @"returnButton": returnButton, - @"continueButton": continueButton, - @"grid": autoGrid, - @"topGuide": self.topLayoutGuide, - @"bottomGuide": self.bottomLayoutGuide, - }; - NSMutableArray *constraints = [[NSMutableArray alloc] init]; - [constraints addObjectsFromArray: - [NSLayoutConstraint constraintsWithVisualFormat: - @"V:[topGuide]-10-[top]-0@100-[big]-0@100-[explain]-18@200-[grid]-18-[continueButton]-8-[returnButton]-20@100-[bottomGuide]" - options:NSLayoutFormatAlignAllCenterX metrics:nil views:viewsDictionary]]; - NSArray *additional = @[ - @"[explain(<=650)]", - @"|-10-[explain]-10-|", - @"|-20-[grid]-20-|", - ]; - for (NSString *fmt in additional) { - [constraints addObjectsFromArray: - [NSLayoutConstraint constraintsWithVisualFormat:fmt options:0 metrics:nil views:viewsDictionary]]; - } - [self.view addConstraints:constraints]; -} - - -- (NSUInteger)supportedInterfaceOrientations -{ - if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) - return UIInterfaceOrientationMaskAll; - else if ([UIScreen mainScreen].bounds.size.width >= 414) - return UIInterfaceOrientationMaskAllButUpsideDown; - else - return UIInterfaceOrientationMaskPortrait; -} - -@end - -@interface AppDelegate : UIResponder <UIApplicationDelegate> { -} - -@property (strong, nonatomic) UIWindow *window; - - -@end - -@implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - NSLog(@"dflwo"); - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - ViewController *viewController = [[ViewController alloc] init]; - self.window.rootViewController = viewController; - [self.window makeKeyAndVisible]; - return YES; -} - -@end - -int main(int argc, char *argv[]) { - NSLog(@"main"); - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, @"AppDelegate"); - } -} - diff --git a/ios-bootstrap/safety-dance/white.png b/ios-bootstrap/safety-dance/white.png Binary files differdeleted file mode 100644 index eab5a56..0000000 --- a/ios-bootstrap/safety-dance/white.png +++ /dev/null diff --git a/ios-bootstrap/unrestrict.c b/ios-bootstrap/unrestrict.c deleted file mode 100644 index 3c6ff56..0000000 --- a/ios-bootstrap/unrestrict.c +++ /dev/null @@ -1,115 +0,0 @@ -#define IB_LOG_NAME "unrestrict" -#include "ib-log.h" -#include "substitute.h" -#include "substitute-internal.h" -#include <stdlib.h> -#include <syslog.h> -#include <signal.h> -#include <errno.h> -#include <stdio.h> - -#define PROC_PIDFDVNODEINFO 1 -#define PROC_PIDFDVNODEINFO_SIZE 176 -int proc_pidfdinfo(int, int, int, void *, int); - -int main(int argc, char **argv) { - if (argc != 4) { - ib_log("unrestrict: wrong number of args"); - return 1; - } - - const char *pids = argv[1]; - char *end; - long pid = strtol(pids, &end, 10); - if (!pids[0] || *end) { - ib_log("unrestrict: pid not an integer"); - return 1; - } - - const char *should_resume = argv[2]; - if (strcmp(should_resume, "0") && strcmp(should_resume, "1")) { - ib_log("unrestrict: should_resume not 0 or 1"); - return 1; - } - - const char *is_exec = argv[3]; - if (strcmp(is_exec, "0") && strcmp(is_exec, "1")) { - ib_log("unrestrict: is_exec not 0 or 1"); - return 1; - } - - /* double fork to avoid zombies */ - int ret = fork(); - if (ret == -1) { - ib_log("unrestrict: fork: %s", strerror(errno)); - return 1; - } else if (ret) { - return 0; - } - - if (IB_VERBOSE) { - ib_log("unrestrict: unrestricting %ld (sr=%s, ie=%s)", pid, - should_resume, is_exec); - } - - int ec = 1; - - mach_port_t task; - kern_return_t kr = task_for_pid(mach_task_self(), (pid_t) pid, &task); - if (kr) { - ib_log("unrestrict: TFP fail: %d", kr); - goto fail; - } - - if (is_exec[0] == '1') { - int retries = 0; - int wait_us = 1; - while (1) { - /* The process might not have transitioned yet. We set up a dummy fd - * 255 in the parent process which was marked CLOEXEC, so test if that - * still exists. AFAICT, Substrate's equivalent to this is not - * actually correct. - * TODO cleanup - */ - char buf[PROC_PIDFDVNODEINFO_SIZE]; - /* A bug in proc_pidfdinfo makes it never return -1. Yuck. */ - errno = 0; - proc_pidfdinfo(pid, 255, PROC_PIDFDVNODEINFO, buf, sizeof(buf)); - if (errno == EBADF) { - break; - } else if (errno) { - ib_log("proc_pidfdinfo: %s", strerror(errno)); - goto fail; - } - - if (retries++ == 20) { - ib_log("still in parent process after 20 retries"); - goto fail; - } - wait_us *= 2; - if (wait_us > 200000) - wait_us = 200000; - while (usleep(wait_us)) - ; - } - } - - char *err = NULL; - int sret = substitute_ios_unrestrict(task, &err); - if (sret) { - ib_log("unrestrict: substitute_ios_unrestrict => %d (%s)", - sret, err); - ec = 1; - } - - ec = 0; -fail: - if (should_resume[0] == '1') { - if ((kill(pid, SIGCONT))) { - ib_log("unrestrict: kill SIGCONT: %s", strerror(errno)); - return 1; - } - } - - return ec; -} |