diff --git a/src/dyld/src/dyldAPIs.cpp b/src/dyld/src/dyldAPIs.cpp index 90c9feeef..c6853b536 100644 --- a/src/dyld/src/dyldAPIs.cpp +++ b/src/dyld/src/dyldAPIs.cpp @@ -83,6 +83,10 @@ static NSLinkEditErrors sLastErrorFileCode; static int sLastErrorNo; #endif +#ifdef DARLING +extern "C" int mach_driver_get_fd(void); +#endif + // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards // This conditional keeps support for old libSystem's which needed some help implementing the API's @@ -208,6 +212,9 @@ static struct dyld_func dyld_funcs[] = { #if OLD_LIBSYSTEM_SUPPORT {"__dyld_link_module", (void*)_dyld_link_module }, #endif +#ifdef DARLING + {"__dyld_get_mach_driver_fd", (void*)mach_driver_get_fd }, +#endif #endif //DEPRECATED_APIS_SUPPORTED {NULL, 0} diff --git a/src/dyld/src/dyldInitialization.cpp b/src/dyld/src/dyldInitialization.cpp index dac7c4439..060c04ec8 100644 --- a/src/dyld/src/dyldInitialization.cpp +++ b/src/dyld/src/dyldInitialization.cpp @@ -195,7 +195,7 @@ static void rebaseDyld(const struct macho_header* mh, intptr_t slide) } -extern "C" void mach_init(); +extern "C" void mach_init(const char* apple[]); extern "C" void __guard_setup(const char* apple[]); @@ -222,7 +222,7 @@ uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* ++apple; // allow dyld to use mach messaging - mach_init(); + mach_init(apple); // set up random value for stack canary __guard_setup(apple); diff --git a/src/kernel/emulation/linux/mach/CMakeLists.txt b/src/kernel/emulation/linux/mach/CMakeLists.txt index a30c4b704..9c0c62a86 100644 --- a/src/kernel/emulation/linux/mach/CMakeLists.txt +++ b/src/kernel/emulation/linux/mach/CMakeLists.txt @@ -15,7 +15,6 @@ set(mach_server_client_sources mach_time.c lkm.c darling_mach_syscall.S - lkm-int.S mach_table.c ) diff --git a/src/kernel/emulation/linux/mach/lkm-int.S b/src/kernel/emulation/linux/mach/lkm-int.S deleted file mode 100644 index 483905fd0..000000000 --- a/src/kernel/emulation/linux/mach/lkm-int.S +++ /dev/null @@ -1,22 +0,0 @@ -.globl _lkm_call - -#if defined(__x86_64__) - -_lkm_call: - movq %rdi, %rax - movq %rsi, %rcx - int $0x83 - ret - -#elif defined(__i386__) - -_lkm_call: - movl 4(%esp), %eax - movl 8(%esp), %ecx - int $0x83 - ret - -#else -#error Missing implementation -#endif - diff --git a/src/kernel/emulation/linux/mach/lkm.c b/src/kernel/emulation/linux/mach/lkm.c index a7eea489a..409c9a9da 100644 --- a/src/kernel/emulation/linux/mach/lkm.c +++ b/src/kernel/emulation/linux/mach/lkm.c @@ -21,8 +21,68 @@ extern _libkernel_functions_t _libkernel_functions; extern void sigexc_setup1(void); extern void sigexc_setup2(void); -void mach_driver_init(void) +static int driver_fd = -1; + +void mach_driver_init(const char** applep) +{ +#ifdef VARIANT_DYLD + if (applep != NULL) + { + int i; + for (i = 0; applep[i] != NULL; i++) + { + if (strncmp(applep[i], "kernfd=", 7) == 0) + { + driver_fd = __simple_atoi(applep[i] + 7, NULL); + break; + } + } + } +#else + // Ask for fd already set up by dyld + int (*p)(void); + _libkernel_functions->dyld_func_lookup("__dyld_get_mach_driver_fd", &p); + + driver_fd = (*p)(); +#endif + + // If mach_driver_init() is being called in the fork child, the LKM will now + // swap out driver_fd for a new one. + if (__real_ioctl(driver_fd, NR_get_api_version, 0) != DARLING_MACH_API_VERSION) + { + const char* msg = "Darling Mach kernel module reports different API level. Aborting.\n"; + sys_write(2, msg, strlen(msg)); + sys_kill(0, 6); + } + + // mach_driver_init() gets called at several points in application's lifetime: + // 1) When dyld loads + // 2) When libc initializes + // 3) After forking +#ifdef VARIANT_DYLD + struct rlimit lim; + if (sys_getrlimit(RLIMIT_NOFILE, &lim) == 0 && driver_fd != lim.rlim_cur) + { + // sys_getrlimit intentionally reports a limit lower by 1 + // so that our fd remains "hidden" to applications. + // It also means rlim_cur is not above the limit + // in the following statement. + int d = sys_dup2(driver_fd, lim.rlim_cur); + sys_close(driver_fd); + + driver_fd = d; + } +#endif +} + +__attribute__((visibility("default"))) +int lkm_call(int call_nr, void* arg) { + return __real_ioctl(driver_fd, call_nr, arg); } +int mach_driver_get_fd(void) +{ + return driver_fd; +} diff --git a/src/kernel/emulation/linux/mach/lkm.h b/src/kernel/emulation/linux/mach/lkm.h index 5b68b0934..22ef22622 100644 --- a/src/kernel/emulation/linux/mach/lkm.h +++ b/src/kernel/emulation/linux/mach/lkm.h @@ -1,7 +1,7 @@ #ifndef _LKM_H #define _LKM_H -void mach_driver_init(void); +void mach_driver_init(const char** applep); int lkm_call(int call_nr, void* arg); diff --git a/src/kernel/emulation/linux/misc/getrlimit.c b/src/kernel/emulation/linux/misc/getrlimit.c index 68802323a..91d9bc877 100644 --- a/src/kernel/emulation/linux/misc/getrlimit.c +++ b/src/kernel/emulation/linux/misc/getrlimit.c @@ -16,6 +16,12 @@ long sys_getrlimit(unsigned int which, struct rlimit* rlp) if (ret < 0) ret = errno_linux_to_bsd(ret); + if (which == LINUX_RLIMIT_NOFILE) + { + rlp->rlim_cur--; + rlp->rlim_max--; + } + return ret; } diff --git a/src/kernel/emulation/linux/misc/setrlimit.c b/src/kernel/emulation/linux/misc/setrlimit.c index d900e7bb7..415aacb01 100644 --- a/src/kernel/emulation/linux/misc/setrlimit.c +++ b/src/kernel/emulation/linux/misc/setrlimit.c @@ -13,6 +13,12 @@ long sys_setrlimit(unsigned int which, const struct rlimit* rlp) if (which == -1) return -EINVAL; + if (which == LINUX_RLIMIT_NOFILE) + { + lim.rlim_cur++; + lim.rlim_max++; + } + ret = LINUX_SYSCALL(__NR_prlimit64, 0, which, &lim, 0); if (ret < 0) ret = errno_linux_to_bsd(ret); diff --git a/src/kernel/emulation/linux/process/posix_spawn.c b/src/kernel/emulation/linux/process/posix_spawn.c index 37d70ca7f..f640d56ec 100644 --- a/src/kernel/emulation/linux/process/posix_spawn.c +++ b/src/kernel/emulation/linux/process/posix_spawn.c @@ -31,7 +31,6 @@ #define LINUX_ADDR_NO_RANDOMIZE 0x40000 -extern void mach_driver_init(void); long sys_posix_spawn(int* pid, const char* path, const struct _posix_spawn_args_desc* desc, char** argvp, char** envp) @@ -48,7 +47,7 @@ long sys_posix_spawn(int* pid, const char* path, const struct _posix_spawn_args_ if ((my_pid = sys_fork()) == 0) { - mach_driver_init(); + mach_driver_init(NULL); // child // close the reading side diff --git a/src/kernel/libsyscall/mach/mach_init.c b/src/kernel/libsyscall/mach/mach_init.c index b1ccdb435..5016a466c 100644 --- a/src/kernel/libsyscall/mach/mach_init.c +++ b/src/kernel/libsyscall/mach/mach_init.c @@ -78,10 +78,10 @@ vm_size_t vm_page_size = 0; vm_size_t vm_page_mask = 0; int vm_page_shift = 0; -int mach_init(void); +int mach_init(const char** applep); int _mach_fork_child(void); -static void mach_init_doit(void); +static void mach_init_doit(const char** applep); extern void _pthread_set_self(void *); extern void _init_cpu_capabilities(void); @@ -99,11 +99,11 @@ host_page_size(__unused host_t host, vm_size_t *out_page_size) * called by libSystem_initializer() in dynamic executables */ int -mach_init(void) +mach_init(const char** applep) { static bool mach_init_inited = false; if (!mach_init_inited) { - mach_init_doit(); + mach_init_doit(applep); mach_init_inited = true; } return 0; @@ -113,7 +113,7 @@ mach_init(void) int _mach_fork_child(void) { - mach_init_doit(); + mach_init_doit(NULL); return 0; } @@ -123,9 +123,9 @@ void _mach_fork_parent(void) } void -mach_init_doit(void) +mach_init_doit(const char** applep) { - mach_driver_init(); + mach_driver_init(applep); // Initialize cached mach ports defined in mach_init.h mach_task_self_ = task_self_trap(); diff --git a/src/kernel/libsyscall/wrappers/_libkernel_init.c b/src/kernel/libsyscall/wrappers/_libkernel_init.c index 629dd9de5..0239e5817 100644 --- a/src/kernel/libsyscall/wrappers/_libkernel_init.c +++ b/src/kernel/libsyscall/wrappers/_libkernel_init.c @@ -28,7 +28,7 @@ #include "_libkernel_init.h" -extern int mach_init(void); +extern int mach_init(const char** applep); extern void sigexc_setup(void); /* dlsym() funcptr is for legacy support in exc_catcher */ @@ -40,7 +40,7 @@ _libkernel_functions_t _libkernel_functions; void __libkernel_init(_libkernel_functions_t fns, const char *envp[] __attribute__((unused)), - const char *apple[] __attribute__((unused)), + const char *apple[], const struct ProgramVars *vars __attribute__((unused))) { _libkernel_functions = fns; @@ -48,6 +48,6 @@ __libkernel_init(_libkernel_functions_t fns, _dlsym = fns->dlsym; } - mach_init(); + mach_init(apple); sigexc_setup(); } diff --git a/src/lkm b/src/lkm index 56f0a2d84..9e261dff1 160000 --- a/src/lkm +++ b/src/lkm @@ -1 +1 @@ -Subproject commit 56f0a2d84783a26ef27e8dde0ba75f4d802be8cc +Subproject commit 9e261dff1c08adf546e74b96fb853548f4f67bd7