From 22f23905306ebbee94a146e55ed261f72c6dabdd Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Fri, 20 Mar 2026 20:27:43 +0100 Subject: [PATCH] Resolve OEM inline hook veneers to prevent infinite recursion On heavily customized Android ROMs, the OEM dynamically hotpatches libart.so methods using a 16-byte ARM64 veneer (`ldr x16/17, pc+8; br x16/17`). When Dobby attempts to hook these pre-applied veneers, its literal relocator handles the `ldr x, pc+offset` instruction incorrectly by reading the overwritten literal pool at runtime, resulting in an infinite recursion loop and a SIGSEGV (stack overflow) in system_server. This commit introduces a workaround for ARM64: we actively check if the target address starts with this known trampoline signature. If found, we extract the absolute address from `pc+8` and apply our hook directly to the OEM's real implementation. This safely chains our hooks onto the OEM's hotpatch framework. Currently experimental and primarily for testing purposes. --- native/include/core/native_api.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/native/include/core/native_api.h b/native/include/core/native_api.h index 1a97e82de..60b24e19a 100644 --- a/native/include/core/native_api.h +++ b/native/include/core/native_api.h @@ -111,10 +111,38 @@ bool InstallNativeAPI(const lsplant::HookHandler &handler); */ void RegisterNativeLib(const std::string &library_name); +#if defined(__aarch64__) +inline void *ResolveOEMVeneer(void *target) { + if (!target) return nullptr; + + auto *insn = static_cast(target); + + // Check for 'ldr x17, pc+8' (0x58000051) followed by 'br x17' (0xd61f0220) + if (insn[0] == 0x58000051 && insn[1] == 0xd61f0220) { + void *real_target = *reinterpret_cast(insn + 2); + LOGW("OEM veneer (x17) detected at {}, resolving to {}", target, real_target); + return real_target; + } + + // Check for 'ldr x16, pc+8' (0x58000050) followed by 'br x16' (0xd61f0200) + if (insn[0] == 0x58000050 && insn[1] == 0xd61f0200) { + void *real_target = *reinterpret_cast(insn + 2); + LOGW("OEM veneer (x16) detected at {}, resolving to {}", target, real_target); + return real_target; + } + + return target; +} +#else +inline void *ResolveOEMVeneer(void *target) { return target; } +#endif + /** * @brief A wrapper around DobbyHook. */ inline int HookInline(void *original, void *replace, void **backup) { + original = ResolveOEMVeneer(original); + if constexpr (kIsDebugBuild) { Dl_info info; if (dladdr(original, &info)) { @@ -132,6 +160,8 @@ inline int HookInline(void *original, void *replace, void **backup) { * @brief A wrapper around DobbyDestroy. */ inline int UnhookInline(void *original) { + original = ResolveOEMVeneer(original); + if constexpr (kIsDebugBuild) { Dl_info info; if (dladdr(original, &info)) {