From 39069e89448893f62ce3e1064563b8f76aa36bdd Mon Sep 17 00:00:00 2001 From: opa334 Date: Fri, 13 Dec 2024 21:30:35 +0100 Subject: [PATCH] Switch forkfix to litehook rebinds on iOS 15 arm64e to hopefully bring back the frequency of spinlock panics to what they were on 2.1.x --- BaseBin/_external/modules/litehook | 2 +- BaseBin/forkfix/Makefile | 2 +- BaseBin/forkfix/src/litehook.h | 6 --- BaseBin/forkfix/src/main.c | 61 +++++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 13 deletions(-) delete mode 100644 BaseBin/forkfix/src/litehook.h diff --git a/BaseBin/_external/modules/litehook b/BaseBin/_external/modules/litehook index f4d083d5c..96704f252 160000 --- a/BaseBin/_external/modules/litehook +++ b/BaseBin/_external/modules/litehook @@ -1 +1 @@ -Subproject commit f4d083d5cb9d215ad96574fae4ce84bc3f7612e9 +Subproject commit 96704f252e401c9903c1d315c6c87a2c05a7f124 diff --git a/BaseBin/forkfix/Makefile b/BaseBin/forkfix/Makefile index e19587dc8..f1bee1040 100644 --- a/BaseBin/forkfix/Makefile +++ b/BaseBin/forkfix/Makefile @@ -1,7 +1,7 @@ TARGET = forkfix.dylib CC = clang -CFLAGS = -I../.include -I./src -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -arch arm64e -miphoneos-version-min=15.0 -O2 +CFLAGS = -I../.include -I./src -I../_external/modules/litehook/src -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -arch arm64e -miphoneos-version-min=15.0 -O2 LDFLAGS = -dynamiclib sign: $(TARGET) diff --git a/BaseBin/forkfix/src/litehook.h b/BaseBin/forkfix/src/litehook.h deleted file mode 100644 index 05d7923c4..000000000 --- a/BaseBin/forkfix/src/litehook.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include -#include - -kern_return_t litehook_hook_function(void *source, void *target); -void *litehook_find_dsc_symbol(const char *imagePath, const char *symbolName); \ No newline at end of file diff --git a/BaseBin/forkfix/src/main.c b/BaseBin/forkfix/src/main.c index f0118ef5f..ee9816760 100644 --- a/BaseBin/forkfix/src/main.c +++ b/BaseBin/forkfix/src/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "syscall.h" #include "litehook.h" #include @@ -92,13 +93,63 @@ __attribute__((visibility ("default"))) pid_t forkfix___fork(void) return pid; } +void apply_fork_hook(void) +{ + static dispatch_once_t onceToken; + dispatch_once (&onceToken, ^{ + void *systemhookHandle = dlopen("systemhook.dylib", RTLD_NOLOAD); + if (systemhookHandle) { + kern_return_t (*litehook_hook_function)(void *source, void *target) = dlsym(systemhookHandle, "litehook_hook_function"); + if (litehook_hook_function) { + litehook_hook_function((void *)__fork, (void *)forkfix___fork); + } + } + }); +} + +// iOS 15 arm64e wrappers +// Only apply fork hook when something actually calls it +int fork_hook(void) +{ + apply_fork_hook(); + return fork(); +} +int vfork_hook(void) +{ + apply_fork_hook(); + return vfork(); +} +pid_t forkpty_hook(int *amaster, char *name, struct termios *termp, struct winsize *winp) +{ + apply_fork_hook(); + return forkpty(amaster, name, termp, winp); +} +int daemon_hook(int __nochdir, int __noclose) +{ + apply_fork_hook(); + return daemon(__nochdir, __noclose); +} + __attribute__((constructor)) static void initializer(void) { - void *systemhookHandle = dlopen("systemhook.dylib", RTLD_NOLOAD); - if (systemhookHandle) { - kern_return_t (*litehook_hook_function)(void *source, void *target) = dlsym(systemhookHandle, "litehook_hook_function"); - if (litehook_hook_function) { - litehook_hook_function((void *)&__fork, (void *)&forkfix___fork); +#ifdef __arm64e__ + if (__builtin_available(iOS 16.0, *)) { /* fall through */ } + else { + void *systemhookHandle = dlopen("systemhook.dylib", RTLD_NOLOAD); + if (systemhookHandle) { + // On iOS 15 arm64e, instead of using instruction replacements, rebind __fork instead + // Less instruction replacements = Less spinlock panics + kern_return_t (*litehook_rebind_symbol_globally)(void *source, void *target) = dlsym(systemhookHandle, "litehook_rebind_symbol_globally"); + if (litehook_rebind_symbol_globally) { + litehook_rebind_symbol_globally((void *)fork, (void *)fork_hook); + litehook_rebind_symbol_globally((void *)vfork, (void *)vfork_hook); + litehook_rebind_symbol_globally((void *)forkpty, (void *)forkpty_hook); + litehook_rebind_symbol_globally((void *)daemon, (void *)daemon_hook); + } } + return; } +#endif + + apply_fork_hook(); } \ No newline at end of file