/* User semaphore syscalls. */ usr_sem_t* syscall_usr_sem_open(const char* name, int value) { return (usr_sem_t*) _syscall(SYSCALL_USR_SEM_OPEN, (uintptr_t) name, (uintptr_t) value, 0); }
/* Close the open file identified by 'filehandle'. Zero will be returned * success, other values indicate errors. */ int syscall_close(int filehandle) { return (int)_syscall(SYSCALL_CLOSE, (uint32_t)filehandle, 0, 0); }
/* Set the file position of the open file identified by 'filehandle' * to 'offset'. Returns 0 on success or a negative value on error. */ int syscall_seek(int filehandle, int offset) { return (int)_syscall(SYSCALL_SEEK, (uint32_t)filehandle, (uint32_t)offset, 0); }
PUBLIC int semup(int sem){ message m; m.m1_i1=sem; return(_syscall(PM_PROC_NR,SEMUP,&m)); }
/* (De)allocate memory by trying to set the heap to end at the address * 'heap_end'. Returns the new end address of the heap, or NULL on * error. If 'heap_end' is NULL, the current heap end is returned. */ void *syscall_memlimit(void *heap_end) { return (void*)_syscall(SYSCALL_MEMLIMIT, (uint32_t)heap_end, 0, 0); }
/* Exit the current process with exit code 'retval'. Note that * 'retval' must be non-negative since syscall_join's negative return * values are interpreted as errors in the join call itself. This * function will never return. */ void syscall_exit(int retval) { _syscall(SYSCALL_EXIT, (uint32_t)retval, 0, 0); }
time_t time(time_t *time) { return ((time_t)_syscall(SYSCALL_TIME, 0, 0, 0, 0, 0)); }
int printmessage() { message m; return(_syscall(PM_PROC_NR, PRINTMESSAGE, &m)); }
/* Create a file with the name 'filename' and initial size of * 'size'. Returns 0 on success and a negative value on error. */ int syscall_create(const char *filename, int size) { return (int)_syscall(SYSCALL_CREATE, (uint32_t)filename, (uint32_t)size, 0); }
/* Load the file indicated by 'filename' as a new process and execute * it, passing the given argv. Returns the process ID of the created * process. Negative values are errors. */ int syscall_spawn(const char *filename, const char **argv) { return (int)_syscall(SYSCALL_SPAWN, (uintptr_t)filename, (uintptr_t)argv, 0); }
MSHook(int, posix_spawn, pid_t *pid, const char *path, const posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char * const argv[], char * const envp[]) { // quit is a goto target that is used below to exit this function without manipulating envp if (false) quit: return _posix_spawn(pid, path, file_actions, attrp, argv, envp); // safe is a goto target that is used below to indicate that Substrate should be removed from envp bool safe(false); if (false) safe: { safe = true; goto scan; } // we use these arguments below, so we need to fix them or fail early if (path == NULL) goto quit; if (envp == NULL) envp = environ; // it is possible we are still installed in the kernel, even though substrate was removed // in this situation, it is safest if we goto safe, not quit, to remove DYLD_INSERT_LIBRARIES if (_syscall(access(SubstrateLibrary_, R_OK | X_OK)) == -1) goto safe; // if a process wants to turn off Substrate for its children, it needs to communicate this to us // a process can also indicate "I'm good, just do it", bypassing the later (expensive) safety checks for (char * const *env(envp); *env != NULL; ++env) if (false); else if (strncmp(SubstrateSafeMode_ "=", *env, sizeof(SubstrateSafeMode_)) == 0) { const char *value(*env + sizeof(SubstrateSafeMode_)); if (false); else if (strcmp(value, "0") == 0 || strcmp(value, "NO") == 0) goto scan; else if (strcmp(value, "1") == 0 || strcmp(value, "YES") == 0 || strcmp(value, "") == 0) goto safe; else goto quit; } // DYLD_INSERT_LIBRARIES does not work in processes that are setugid // testing this condition prevents us from having a runaway test below struct stat info; if (_syscall(stat(path, &info)) == -1) goto safe; if ((info.st_mode & S_ISUID) != 0 && getuid() != info.st_uid) goto safe; // XXX: technically, if this user is not a member of the group if ((info.st_mode & S_ISGID) != 0 && getgid() != info.st_gid) goto safe; // some jailbreaks (example: iOS 3.0 PwnageTool) have broken (restrictive) sandbox patches // spawning the process with DYLD_INSERT_LIBRARIES causes them to immediately crash switch (pid_t child = _syscall(fork())) { case -1: goto quit; case 0: // XXX: figure out a way to turn off CrashReporter for this process _syscall(execle(path, path, NULL, (const char *[]) { SubstrateVariable_ "=" SubstrateLibrary_, "MSExitZero" "=", NULL })); _exit(EXIT_FAILURE); default: int status; if (_syscall(waitpid(child, &status, 0)) == -1) goto safe; if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) goto safe; }
int syscall_usr_sem_vacate(usr_sem_t* handle) { return (int) _syscall(SYSCALL_USR_SEM_VACATE, (uintptr_t) handle, 0, 0); }
int syscall_usr_sem_procure(usr_sem_t* handle) { return (int) _syscall(SYSCALL_USR_SEM_PROCURE, (uintptr_t) handle, 0, 0); }
int syscall_usr_sem_destroy(usr_sem_t* handle) { return (int) _syscall(SYSCALL_USR_SEM_DESTROY, (uintptr_t) handle, 0, 0); }
/* Load the file indicated by 'filename' as a new process and execute * it. Returns the process ID of the created process. Negative values * are errors. */ pid_t syscall_exec(const char *filename) { return (int)_syscall(SYSCALL_EXEC, (uint32_t)filename, 0, 0); }
/* Create a file with the name 'filename' and initial size of * 'size'. Returns 0 on success and a negative value on error. */ int syscall_delete(const char *filename) { return (int)_syscall(SYSCALL_DELETE, (uint32_t)filename, 0, 0); }
/* Load the file indicated by 'filename' as a new process and execute * it. Returns the process ID of the created process. Negative values * are errors. */ pid_t syscall_execp(const char *filename, int argc, const char **argv) { return (int)_syscall(SYSCALL_EXEC, (uint32_t)filename, (uint32_t) argc, (uint32_t) argv); }
int syscall_sleep(int msec) { return (int)_syscall(SYSCALL_SLEEP, (uint32_t)msec, 0, 0); }
/* Wait until the execution of the process identified by 'pid' is * finished. Returns the exit code of the joined process, or a * negative value on error. */ int syscall_join(pid_t pid) { return (int)_syscall(SYSCALL_JOIN, (uint32_t)pid, 0, 0); }
int syscall_yield(void) { return (int)_syscall(SYSCALL_YIELD, 0, 0, 0); }
pid_t getpgrp() { message m; return(_syscall(PM_PROC_NR, GETPGRP, &m)); }
int syscall_sem_create(usr_sem_t *sem, int val) { return (int)_syscall(SYSCALL_SEM_CREATE, (uint32_t)sem, (uint32_t)val, 0); }
/* Create a new thread running in the same address space as the * caller. The thread is started at function 'func', and the thread * will end when 'func' returns. 'arg' is passed as an argument to * 'func'. Returns 0 on success or a negative value on error. */ int syscall_fork(void (*func)(int), int arg) { return (int)_syscall(SYSCALL_FORK, (uint32_t)func, (uint32_t)arg, 0); }
int syscall_sem_v(usr_sem_t *sem) { return (int)_syscall(SYSCALL_SEM_V, (uint32_t)sem, 0, 0); }
/* Open the file identified by 'filename' for reading and * writing. Returns the file handle of the opened file (positive * value), or a negative value on error. */ int syscall_open(const char *filename) { return (int)_syscall(SYSCALL_OPEN, (uint32_t)filename, 0, 0); }
/** * Returns the elapsed milliseconds since system startup. * * @return The elapsed time in milliseconds. */ int syscall_get_time_from_start(void) { return (int)_syscall(SYSCALL_SYSTEM_TIME,0,0,0); }
/* Read 'length' bytes from the open file identified by 'filehandle' * into 'buffer', starting at the current file position. Returns the * number of bytes actually read (e.g. 0 if the file position is at * the end of file) or a negative value on error. */ int syscall_read(int filehandle, void *buffer, int length) { return (int)_syscall(SYSCALL_READ, (uint32_t)filehandle, (uint32_t)buffer, (uint32_t)length); }
/* Halt the system (sync disks and power off). This function will * never return. */ void syscall_halt(void) { _syscall(SYSCALL_HALT, 0, 0, 0); }
/* Write 'length' bytes from 'buffer' to the open file identified by * 'filehandle', starting from the current file position. Returns the * number of bytes actually written or a negative value on error. */ int syscall_write(int filehandle, const void *buffer, int length) { return (int)_syscall(SYSCALL_WRITE, (uint32_t)filehandle, (uint32_t)buffer, (uint32_t)length); }
/* Get the name of the idx'th file in the given directory. */ int syscall_file(const char *pathname, int idx, char *buffer) { return (int)_syscall(SYSCALL_FILE, (uintptr_t)pathname, (uintptr_t)idx, (uintptr_t)buffer); }