diff options
author | comex | 2015-01-29 21:49:37 -0500 |
---|---|---|
committer | comex | 2015-01-29 21:49:37 -0500 |
commit | 76a805974a7b177a4ea6b5587fe8551087ac1505 (patch) | |
tree | 84cef385a74b34e0cdd1489848f6da39ed032233 /ios-bootstrap/unrestrict.c | |
parent | a bunch of stuff that should have been committed separately (diff) | |
download | substitute-76a805974a7b177a4ea6b5587fe8551087ac1505.tar.gz |
...
Diffstat (limited to 'ios-bootstrap/unrestrict.c')
-rw-r--r-- | ios-bootstrap/unrestrict.c | 87 |
1 files changed, 70 insertions, 17 deletions
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; } |