aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcomex2015-01-29 21:49:37 -0500
committercomex2015-01-29 21:49:37 -0500
commit76a805974a7b177a4ea6b5587fe8551087ac1505 (patch)
tree84cef385a74b34e0cdd1489848f6da39ed032233
parenta bunch of stuff that should have been committed separately (diff)
downloadsubstitute-76a805974a7b177a4ea6b5587fe8551087ac1505.tar.gz
...
-rw-r--r--Makefile4
-rw-r--r--ios-bootstrap/ib-log.h26
-rw-r--r--ios-bootstrap/posixspawn-hook.c76
-rw-r--r--ios-bootstrap/unrestrict.c87
-rw-r--r--lib/darwin/unrestrict.c50
-rw-r--r--lib/substitute-internal.h2
6 files changed, 129 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index 091bf59..7cca0d2 100644
--- a/Makefile
+++ b/Makefile
@@ -175,10 +175,10 @@ out/posixspawn-hook.dylib: ios-bootstrap/posixspawn-hook.c out/libsubstitute.dyl
$(CC) -dynamiclib -o $@ $< -Lout -lsubstitute
out/bundle-loader.dylib: ios-bootstrap/bundle-loader.m out/libsubstitute.dylib
$(CC) -dynamiclib -o $@ $< -fobjc-arc -Lout -framework Foundation -framework CoreFoundation
-out/unrestrict: ios-bootstrap/unrestrict.c out/libsubstitute.dylib
+out/unrestrict: ios-bootstrap/unrestrict.c ios-bootstrap/ib-log.h out/libsubstitute.dylib
$(CC) -o $@ $< -Lout -lsubstitute
ldid -Sent.plist $@
-out/inject-into-launchd: ios-bootstrap/inject-into-launchd.c out/libsubstitute.dylib
+out/inject-into-launchd: ios-bootstrap/inject-into-launchd.c ios-bootstrap/ib-log.h out/libsubstitute.dylib
$(CC) -o $@ $< -Lout -lsubstitute -framework IOKit -framework CoreFoundation
ldid -Sent.plist $@
all: out/posixspawn-hook.dylib out/bundle-loader.dylib out/unrestrict out/inject-into-launchd
diff --git a/ios-bootstrap/ib-log.h b/ios-bootstrap/ib-log.h
new file mode 100644
index 0000000..f4b0b35
--- /dev/null
+++ b/ios-bootstrap/ib-log.h
@@ -0,0 +1,26 @@
+#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)
+
diff --git a/ios-bootstrap/posixspawn-hook.c b/ios-bootstrap/posixspawn-hook.c
index f1aff4e..ec384c9 100644
--- a/ios-bootstrap/posixspawn-hook.c
+++ b/ios-bootstrap/posixspawn-hook.c
@@ -1,3 +1,5 @@
+#define IB_LOG_NAME "posixspawn-hook"
+#include "ib-log.h"
#include "substitute.h"
#include "substitute-internal.h"
#include <mach/mach.h>
@@ -7,33 +9,10 @@
#include <syslog.h>
#include <malloc/malloc.h>
#include <assert.h>
-#include <dispatch/dispatch.h>
#include <errno.h>
extern char ***_NSGetEnviron(void);
-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-posixspawn-hook-log.%ld",
- (long) getpid());
- logfp = fopen(filename, "w");
- if (!logfp) {
- /* Ack... */
- logfp = stderr;
- }
- });
-}
-#define psh_log(fmt, args...) do { \
- open_logfp_if_necessary(); \
- syslog(LOG_EMERG, fmt, ##args); \
- fprintf(logfp, fmt "\n", ##args); \
- fflush(logfp); \
-} while(0)
-
static __typeof__(posix_spawn) *old_posix_spawn, *old_posix_spawnp,
hook_posix_spawn, hook_posix_spawnp;
static __typeof__(wait4) *old_wait4, hook_wait4;
@@ -48,22 +27,23 @@ static bool advance(char **strp, const char *template) {
return false;
}
-static bool spawn_unrestrict(pid_t pid, bool should_resume) {
+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 *argv[] = {prog, pid_s, should_resume_s, NULL};
+ 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)) {
- psh_log("posixspawn-hook: couldn't start unrestrict-me - oh well...");
+ ib_log("posixspawn-hook: couldn't start unrestrict-me - 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)
- psh_log("posixspawn-hook: couldn't waitpid");
- psh_log("unrestrict xstat=%x", xstat);
+ ib_log("posixspawn-hook: couldn't waitpid");
+ ib_log("unrestrict xstat=%x", xstat);
return true;
}
@@ -94,12 +74,12 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old,
short flags;
if (posix_spawnattr_getflags(&my_attr, &flags))
goto crap;
- psh_log("hook_posix_spawn_generic: path=%s%s%s",
- path,
- (flags & POSIX_SPAWN_SETEXEC) ? " (exec)" : "",
- (flags & POSIX_SPAWN_START_SUSPENDED) ? " (suspend)" : "");
+ 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++)
- psh_log(" %s", *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
@@ -160,7 +140,7 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old,
: my_dylib_1;
newp = stpcpy(newp, dylib_to_add);
}
- psh_log("using %s", new);
+ ib_log("using %s", new);
/* no libraries? then just get rid of it */
if (newp == newp_orig) {
free(new);
@@ -192,18 +172,18 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old,
if (flags & POSIX_SPAWN_SETEXEC) {
/* make the marker fd; hope you weren't using that */
if (dup2(2, 255) != 255) {
- psh_log("dup2 failure - %s", strerror(errno));
+ ib_log("dup2 failure - %s", strerror(errno));
goto skip;
}
if (fcntl(255, F_SETFD, FD_CLOEXEC))
goto crap;
- psh_log("spawning unrestrict");
- if (!spawn_unrestrict(getpid(), !was_suspended))
+ ib_log("spawning unrestrict");
+ if (!spawn_unrestrict(getpid(), !was_suspended, true))
goto skip;
}
- psh_log("**");
+ ib_log("**");
int ret = old(pidp, path, file_actions, &my_attr, argv, envp_to_use);
- psh_log("ret=%d pid=%ld", ret, (long) *pidp);
+ 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
@@ -221,21 +201,21 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old,
0);
dispatch_async(q, ^{
char *error;
- psh_log("unrestricting %d", pid);
+ ib_log("unrestricting %d", pid);
int sret = substitute_ios_unrestrict(pid, !was_suspended, &error);
- psh_log("unrestricting done");
+ ib_log("unrestricting done");
if (sret) {
- psh_log("posixspawn-hook: substitute_ios_unrestrict => %d (%s)",
+ ib_log("posixspawn-hook: substitute_ios_unrestrict => %d (%s)",
sret, error);
}
free(error);
});
#else
- spawn_unrestrict(pid, !was_suspended);
+ spawn_unrestrict(pid, !was_suspended, false);
#endif
goto cleanup;
crap:
- psh_log("posixspawn-hook: weird error - OOM? skipping our stuff");
+ ib_log("posixspawn-hook: weird error - OOM? skipping our stuff");
skip:
ret = old(pidp, path, file_actions, attrp, argv, envp);
cleanup:
@@ -282,7 +262,7 @@ pid_t hook_waitpid(pid_t pid, int *stat_loc, int options) {
void substitute_init(struct shuttle *shuttle, size_t nshuttle) {
/* Just tell them we're done */
if (nshuttle != 1) {
- psh_log("nshuttle = %zd?", nshuttle);
+ ib_log("nshuttle = %zd?", nshuttle);
return;
}
mach_port_t notify_port = shuttle[0].u.mach.port;
@@ -295,7 +275,7 @@ void substitute_init(struct shuttle *shuttle, size_t nshuttle) {
done_hdr.msgh_id = 42;
kern_return_t kr = mach_msg_send(&done_hdr);
if (kr)
- psh_log("posixspawn-hook: mach_msg_send failed: kr=%x", kr);
+ ib_log("posixspawn-hook: mach_msg_send failed: kr=%x", kr);
/* MOVE deallocated the port */
}
@@ -318,7 +298,7 @@ static void init() {
struct substitute_image *im = substitute_open_image(_dyld_get_image_name(0));
if (!im) {
- psh_log("posixspawn-hook: substitute_open_image failed");
+ ib_log("posixspawn-hook: substitute_open_image failed");
goto end;
}
@@ -331,7 +311,7 @@ static void init() {
int err = substitute_interpose_imports(im, hooks, sizeof(hooks)/sizeof(*hooks), 0);
if (err) {
- psh_log("posixspawn-hook: substitute_interpose_imports failed: %s",
+ ib_log("posixspawn-hook: substitute_interpose_imports failed: %s",
substitute_strerror(err));
goto end;
}
diff --git a/ios-bootstrap/unrestrict.c b/ios-bootstrap/unrestrict.c
index b77bdf5..d966670 100644
--- a/ios-bootstrap/unrestrict.c
+++ b/ios-bootstrap/unrestrict.c
@@ -1,53 +1,106 @@
+#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) {
- char filename[128];
- sprintf(filename, "/tmp/wtf.%ld",
- (long) getpid());
- FILE *fp = fopen(filename, "w");
- if (!fp)
- return 1;
- #define syslog(a, b...) fprintf(fp, b)
- if (argc != 3) {
- syslog(LOG_EMERG, "unrestrict: wrong number of args");
+ 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) {
- syslog(LOG_EMERG, "unrestrict: pid not an integer");
+ ib_log("unrestrict: pid not an integer");
return 1;
}
const char *should_resume = argv[2];
if (strcmp(should_resume, "0") && strcmp(should_resume, "1")) {
- syslog(LOG_EMERG, "unrestrict: should_resume not 0 or 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) {
- syslog(LOG_EMERG, "unrestrict: fork: %s", strerror(errno));
+ ib_log("unrestrict: fork: %s", strerror(errno));
return 1;
} else if (ret) {
return 0;
}
+ ib_log("unrestrict: unrestricting %d (sr=%s, ie=%s)", (int) pid,
+ should_resume, is_exec);
+
+ mach_port_t task;
+ kern_return_t kr = task_for_pid(mach_task_self(), pid, &task);
+ if (kr) {
+ ib_log("unrestrict: TFP fail: %d", kr);
+ return 1;
+ }
+
+ 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];
+ int ret = proc_pidfdinfo(pid, 255, PROC_PIDFDVNODEINFO,
+ buf, sizeof(buf));
+ if (ret == -1 && errno == EBADF) {
+ break;
+ } else if (ret == -1) {
+ ib_log("proc_pidfdinfo: %s", strerror(errno));
+ return 1;
+ }
+
+ if (retries++ == 20) {
+ ib_log("still in parent process after 20 retries");
+ return 1;
+ }
+ wait_us *= 2;
+ if (wait_us > 200000)
+ wait_us = 200000;
+ while (usleep(wait_us))
+ ;
+ }
+ }
+
char *err = NULL;
- syslog(LOG_EMERG, "unrestrict: unrestricting %d (%s)", (int) pid, should_resume);
- int sret = substitute_ios_unrestrict((pid_t) pid, should_resume[0] == '1', &err);
+ int sret = substitute_ios_unrestrict(task, &err);
if (sret) {
- syslog(LOG_EMERG, "unrestrict: substitute_ios_unrestrict => %d (%s)",
+ ib_log("unrestrict: substitute_ios_unrestrict => %d (%s)",
sret, err);
- return 1;
}
- return 0;
+ if (should_resume[0] == '1') {
+ if ((kill(pid, SIGCONT))) {
+ ib_log("unrestrict: kill SIGCONT: %s", strerror(errno));
+ return 1;
+ }
+ }
+
+ return sret;
}
diff --git a/lib/darwin/unrestrict.c b/lib/darwin/unrestrict.c
index 70b089a..a0b6ade 100644
--- a/lib/darwin/unrestrict.c
+++ b/lib/darwin/unrestrict.c
@@ -3,14 +3,9 @@
#include "darwin/mach-decls.h"
#include <unistd.h>
#include <stdio.h>
-#include <signal.h>
#include <errno.h>
#include <mach/vm_region.h>
-#define PROC_PIDFDVNODEINFO 1
-#define PROC_PIDFDVNODEINFO_SIZE 176
-int proc_pidfdinfo(int, int, int, void *, int);
-
static int unrestrict_macho_header(void *header, size_t size, bool *did_modify_p,
char **error) {
*did_modify_p = false;
@@ -64,46 +59,12 @@ static int unrestrict_macho_header(void *header, size_t size, bool *did_modify_p
}
EXPORT
-int substitute_ios_unrestrict(pid_t pid, bool should_resume, char **error) {
+int substitute_ios_unrestrict(task_t task, char **error) {
*error = NULL;
- mach_port_t task;
- kern_return_t kr = task_for_pid(mach_task_self(), pid, &task);
- if (kr)
- return SUBSTITUTE_ERR_TASK_FOR_PID;
int ret;
vm_address_t header_addr = 0;
-
- int retries = 0;
- int wait_us = 1;
- while (1) {
- /* If calling from unrestrict-me, 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];
- int ret = proc_pidfdinfo(pid, 255, PROC_PIDFDVNODEINFO, buf, sizeof(buf));
- if (ret == -1 && errno == EBADF) {
- break;
- } else if (ret == -1) {
- asprintf(error, "proc_pidfdinfo: %s", strerror(errno));
- ret = SUBSTITUTE_ERR_MISC;
- goto fail;
- }
-
- if (retries++ == 20) {
- asprintf(error, "still in parent process after 20 retries");
- ret = SUBSTITUTE_ERR_MISC;
- goto fail;
- }
- wait_us *= 2;
- if (wait_us > 100000)
- wait_us = 100000;
- while (usleep(wait_us))
- ;
- }
+ kern_return_t kr;
/* alrighty then, let's look at the damage. find the first readable
* segment */
@@ -176,13 +137,6 @@ setback:;
ret = SUBSTITUTE_OK;
fail:
- if (should_resume) {
- if ((kill(pid, SIGCONT))) {
- asprintf(error, "kill: %s", strerror(errno));
- ret = SUBSTITUTE_ERR_MISC;
- }
- }
- mach_port_deallocate(mach_task_self(), task);
if (header_addr)
vm_deallocate(mach_task_self(), header_addr, toread);
return ret;
diff --git a/lib/substitute-internal.h b/lib/substitute-internal.h
index e240020..f93d1eb 100644
--- a/lib/substitute-internal.h
+++ b/lib/substitute-internal.h
@@ -86,5 +86,5 @@ int substitute_dlopen_in_pid(int pid, const char *filename, int options,
const struct shuttle *shuttle, size_t nshuttle,
char **error);
-int substitute_ios_unrestrict(pid_t pid, bool should_resume, char **error);
+int substitute_ios_unrestrict(task_t task, char **error);
#endif