diff --git a/src/dyld/darling.c b/src/dyld/darling.c index 7ac432699..1059c4d07 100644 --- a/src/dyld/darling.c +++ b/src/dyld/darling.c @@ -42,8 +42,9 @@ along with Darling. If not, see . const char* DARLING_INIT_COMM = "darling-init"; char *prefix; uid_t g_originalUid, g_originalGid; +char **g_argv, **g_envp; -int main(int argc, char const ** argv) +int main(int argc, char ** argv, char ** envp) { pid_t pidInit, pidChild; int wstatus; @@ -54,18 +55,24 @@ int main(int argc, char const ** argv) return 1; } + g_argv = argv; + g_envp = envp; + if (geteuid() != 0) { missingSetuidRoot(); return 1; } - if (loadKernelModule()) - return 1; - g_originalUid = getuid(); g_originalGid = getgid(); + setuid(0); + setgid(0); + + if (!isModuleLoaded()) + loadKernelModule(); + prefix = getenv("DPREFIX"); if (!prefix) prefix = defaultPrefixPath(); @@ -88,7 +95,7 @@ int main(int argc, char const ** argv) }; int option_index = 0; - c = getopt_long(argc, (char *const *)argv, "", long_options, &option_index); + c = getopt_long(argc, argv, "", long_options, &option_index); if (c == -1) { @@ -199,7 +206,6 @@ int main(int argc, char const ** argv) waitpid(pidChild, &wstatus, 0); - // Should we unloadKernelModule() here? Others may be still using it if (WIFEXITED(wstatus)) return WEXITSTATUS(wstatus); if (WIFSIGNALED(wstatus)) @@ -274,9 +280,11 @@ pid_t spawnChild(int pidInit, const char *path, const char *const argv[]) exit(1); } */ - - setresuid(g_originalUid, g_originalUid, g_originalUid); + + // Drop the privileges. It's important to drop GID first, because + // non-root users can't change their GID. setresgid(g_originalGid, g_originalGid, g_originalGid); + setresuid(g_originalUid, g_originalUid, g_originalUid); /* if (setns(fdNS, CLONE_NEWUSER) != 0) @@ -406,6 +414,7 @@ pid_t spawnInitProcess(void) char *opts; char putOld[4096]; + char *p; close(pipefd[0]); @@ -452,12 +461,16 @@ pid_t spawnInitProcess(void) exit(1); } - // Drop the privileges - setresuid(g_originalUid, g_originalUid, g_originalUid); + // Drop the privileges. It's important to drop GID first, because + // non-root users can't change their GID. setresgid(g_originalGid, g_originalGid, g_originalGid); + setresuid(g_originalUid, g_originalUid, g_originalUid); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); + // Set name to darling-init prctl(PR_SET_NAME, DARLING_INIT_COMM, 0, 0); + p = stpcpy(g_argv[0], DARLING_INIT_COMM); + memset(p, 0, g_envp[0] - p); /* if (unshare(CLONE_NEWUSER) != 0) @@ -843,41 +856,26 @@ int isModuleLoaded() return 0; } -int loadKernelModule() +void loadKernelModule() { - FILE* fp; - char output[1024]; - - if ((fp = popen("/sbin/modprobe darling-mach", "r")) == NULL) - { - fprintf(stderr, "Failed to run modprobe\n"); - return 1; - } + int status; + FILE *fp = popen("/sbin/modprobe darling-mach", "w"); - while (fgets(output, sizeof(output), fp) != NULL) + if (fp == NULL) { - printf("%s", output); + fprintf(stderr, "Failed to run modprobe: %s\n", strerror(errno)); + exit(1); } - if (WEXITSTATUS(pclose(fp)) == 0) + status = pclose(fp); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - fprintf(stderr, "Loaded kernel module successfully\n"); - return 0; + fprintf(stderr, "Loaded the kernel module\n"); + return; } else { fprintf(stderr, "Failed to load the kernel module\n"); - return 1; - } -} - -int unloadKernelModule() -{ - if(syscall(SYS_delete_module, "darling_mach", 0)) - { - fprintf(stderr, "Cannot unload kernel module: %s\n", strerror(errno)); - return 1; + exit(1); } - - return 0; } diff --git a/src/dyld/darling.h b/src/dyld/darling.h index 9d9c94371..a19333de5 100644 --- a/src/dyld/darling.h +++ b/src/dyld/darling.h @@ -64,8 +64,6 @@ void checkPrefixOwner(void); int isModuleLoaded(void); -int loadKernelModule(void); - -int unloadKernelModule(void); +void loadKernelModule(void); #endif