aboutsummaryrefslogtreecommitdiff
path: root/ios-bootstrap/unrestrict.c
diff options
context:
space:
mode:
authorcomex2015-01-29 21:49:37 -0500
committercomex2015-01-29 21:49:37 -0500
commit76a805974a7b177a4ea6b5587fe8551087ac1505 (patch)
tree84cef385a74b34e0cdd1489848f6da39ed032233 /ios-bootstrap/unrestrict.c
parenta bunch of stuff that should have been committed separately (diff)
downloadsubstitute-76a805974a7b177a4ea6b5587fe8551087ac1505.tar.gz
...
Diffstat (limited to 'ios-bootstrap/unrestrict.c')
-rw-r--r--ios-bootstrap/unrestrict.c87
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;
}