aboutsummaryrefslogtreecommitdiff
path: root/ios-bootstrap
diff options
context:
space:
mode:
authorcomex2015-02-28 13:16:36 -0500
committercomex2015-02-28 13:16:36 -0500
commitd9a7a8a4d4a23fb65e6319e0e8a435046cc39fea (patch)
treedd219509fc92e695317b82d5dca43296daaf2ab1 /ios-bootstrap
parentremove deprecated property usage in safety-dance (diff)
downloadsubstitute-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.m161
-rw-r--r--ios-bootstrap/ib-log.h27
-rw-r--r--ios-bootstrap/inject-into-launchd.c90
-rw-r--r--ios-bootstrap/posixspawn-hook.c352
-rw-r--r--ios-bootstrap/safety-dance/AutoGrid.h17
-rw-r--r--ios-bootstrap/safety-dance/AutoGrid.m106
-rw-r--r--ios-bootstrap/safety-dance/Info.plist88
-rw-r--r--ios-bootstrap/safety-dance/main.m159
-rw-r--r--ios-bootstrap/safety-dance/white.pngbin1047 -> 0 bytes
-rw-r--r--ios-bootstrap/unrestrict.c115
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
deleted file mode 100644
index eab5a56..0000000
--- a/ios-bootstrap/safety-dance/white.png
+++ /dev/null
Binary files differ
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;
-}