diff --git a/magisk-modules/tng_exit_guard/jni/main.cpp b/magisk-modules/tng_exit_guard/jni/main.cpp index 3b6c09c..78f71c9 100644 --- a/magisk-modules/tng_exit_guard/jni/main.cpp +++ b/magisk-modules/tng_exit_guard/jni/main.cpp @@ -123,21 +123,64 @@ static void promon_segv_handler(int sig, siginfo_t *info, void *ctx) { raise(SIGSEGV); } -/** libc++abi __cxa_guard_acquire 递归初始化 → abort;跳回 LR 继续而非杀进程。 */ +static std::atomic g_main_tid{0}; +static std::atomic g_abrt_swallow{0}; +static std::atomic g_abrt_last_tid{0}; +static std::atomic g_abrt_last_pc{0}; +static std::atomic g_abrt_streak{0}; +static constexpr int kMaxAbrtStreak = 3; + +/** ABRT/TRAP:pc+4 或远距 LR;同 tid+pc 连触发则 freeze,避免 LR 自旋死循环。 */ static void fatal_skip_handler(int sig, siginfo_t *info, void *ctx) { (void)info; ucontext_t *uc = reinterpret_cast(ctx); #if defined(__aarch64__) uintptr_t pc = uc->uc_mcontext.pc; uintptr_t lr = uc->uc_mcontext.regs[30]; - LOGI("swallowed signal %d tid=%d pc=%lx lr=%lx", sig, (int)gettid(), - (unsigned long)pc, (unsigned long)lr); - if (lr != 0) { - uc->uc_mcontext.pc = lr; + pid_t tid = gettid(); + + if (sig == SIGABRT) { + int streak = 1; + if (g_abrt_last_tid.load() == tid && g_abrt_last_pc.load() == pc) { + streak = g_abrt_streak.fetch_add(1) + 1; + } else { + g_abrt_last_tid.store(tid); + g_abrt_last_pc.store(pc); + g_abrt_streak.store(1); + } + if (streak > kMaxAbrtStreak) { + if (tid == g_main_tid.load()) { + LOGI("ABRT main-thread streak cap tid=%d pc=%lx — pc+4 bail", (int)tid, + (unsigned long)pc); + uc->uc_mcontext.pc = pc + 4; + g_abrt_streak.store(0); + return; + } + LOGI("ABRT streak cap tid=%d pc=%lx n=%d — freeze thread", (int)tid, + (unsigned long)pc, streak); + freeze_forever(); + } + uintptr_t delta = (pc > lr) ? (pc - lr) : (lr - pc); + uintptr_t target = pc + 4; + /* lr 距 pc 很近时仍在 abort/epilogue 内,跳 LR 会 instant 再 ABRT */ + if (lr != 0 && delta > 64) { + target = lr; + } + int n = ++g_abrt_swallow; + if (n <= 3 || n % 100 == 0) { + LOGI("ABRT skip tid=%d pc=%lx lr=%lx streak=%d -> %lx", (int)tid, + (unsigned long)pc, (unsigned long)lr, streak, + (unsigned long)target); + } + uc->uc_mcontext.pc = target; return; } - if (pc != 0) { - uc->uc_mcontext.pc = pc + 4; + + if (sig == SIGTRAP) { + uintptr_t target = pc != 0 ? pc + 4 : lr; + LOGI("TRAP skip tid=%d pc=%lx -> %lx", (int)tid, (unsigned long)pc, + (unsigned long)target); + uc->uc_mcontext.pc = target; return; } #endif @@ -151,7 +194,7 @@ static void install_fatal_skip_handlers() { sigemptyset(&sa.sa_mask); sigaction(SIGABRT, &sa, nullptr); sigaction(SIGTRAP, &sa, nullptr); - LOGI("fatal skip handlers (ABRT+TRAP→LR)"); + LOGI("fatal skip handlers (ABRT pc+4/streak-freeze + TRAP pc+4)"); } static void install_promon_segv_handler() { @@ -177,7 +220,7 @@ static void install_soft_signals() { sigaction(SIGABRT, &sa, nullptr); sigaction(SIGTRAP, &sa, nullptr); if (g_soft_sig_logged.fetch_add(1) == 0) { - LOGI("soft signals (ABRT+TRAP skip→LR)"); + LOGI("soft signals (ABRT streak-freeze + TRAP pc+4)"); } } @@ -342,7 +385,9 @@ static void *phase_thread(void *) { } static void install_all(zygisk::Api *api) { - LOGI("install pid=%d (PLT+ABRT/TRAP-skip+pc==lr-SEGV+exit_group@400ms)", getpid()); + g_main_tid.store(gettid()); + LOGI("install pid=%d main_tid=%d (PLT+ABRT-streak-freeze+TRAP+pc==lr-SEGV+exit_group@400ms)", + getpid(), (int)g_main_tid.load()); install_fatal_skip_handlers(); install_soft_signals(); install_plt(api); diff --git a/magisk-modules/tng_exit_guard/zygisk/arm64-v8a.so b/magisk-modules/tng_exit_guard/zygisk/arm64-v8a.so index 98a1bdc..e58a653 100644 Binary files a/magisk-modules/tng_exit_guard/zygisk/arm64-v8a.so and b/magisk-modules/tng_exit_guard/zygisk/arm64-v8a.so differ