From 1d7de6c78e881732abfd398217f83b3476d69655 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Fri, 30 Aug 2024 16:50:30 +0200 Subject: [PATCH] Avoid resolving `libart` symbols twice LSPlt is only used to hook libart symbols. The file `native_util.h` is reformatted by clangd. Fallback to Dobby if LSPlt fails. --- core/src/main/jni/include/config.h | 1 - core/src/main/jni/include/native_util.h | 130 ++++++++---------- core/src/main/jni/src/native_api.cpp | 7 +- core/src/main/jni/src/native_api.h | 10 +- external/lsplant | 2 +- .../src/main/jni/src/magisk_loader.cpp | 8 +- 6 files changed, 74 insertions(+), 84 deletions(-) diff --git a/core/src/main/jni/include/config.h b/core/src/main/jni/include/config.h index 1a91e325..c3f649f5 100644 --- a/core/src/main/jni/include/config.h +++ b/core/src/main/jni/include/config.h @@ -31,7 +31,6 @@ namespace lspd { //#define LOG_DISABLED //#define DEBUG - using lsplant::operator""_tstr; inline bool constexpr Is64() { #if defined(__LP64__) diff --git a/core/src/main/jni/include/native_util.h b/core/src/main/jni/include/native_util.h index f4d0da49..68bf7b01 100644 --- a/core/src/main/jni/include/native_util.h +++ b/core/src/main/jni/include/native_util.h @@ -19,27 +19,30 @@ */ #include -#include "lsplt.hpp" #include + +#include "elf_util.h" +#include "lsplt.hpp" +#include "symbol_cache.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" #pragma once #include -#include "utils/jni_helper.hpp" -#include "logging.h" -#include "config.h" + #include + +#include "../src/native_api.h" +#include "config.h" #include "config_bridge.h" +#include "logging.h" +#include "utils/jni_helper.hpp" namespace lspd { [[gnu::always_inline]] -inline bool RegisterNativeMethodsInternal(JNIEnv *env, - std::string_view class_name, - const JNINativeMethod *methods, - jint method_count) { - +inline bool RegisterNativeMethodsInternal(JNIEnv *env, std::string_view class_name, + const JNINativeMethod *methods, jint method_count) { auto clazz = Context::GetInstance()->FindClassFromCurrentLoader(env, class_name.data()); if (clazz.get() == nullptr) { LOGF("Couldn't find class: {}", class_name.data()); @@ -49,93 +52,80 @@ inline bool RegisterNativeMethodsInternal(JNIEnv *env, } #if defined(__cplusplus) -#define _NATIVEHELPER_JNI_MACRO_CAST(to) \ - reinterpret_cast +#define _NATIVEHELPER_JNI_MACRO_CAST(to) reinterpret_cast #else -#define _NATIVEHELPER_JNI_MACRO_CAST(to) \ - (to) +#define _NATIVEHELPER_JNI_MACRO_CAST(to) (to) #endif #ifndef LSP_NATIVE_METHOD -#define LSP_NATIVE_METHOD(className, functionName, signature) \ - { #functionName, \ - signature, \ - _NATIVEHELPER_JNI_MACRO_CAST(void*) (Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName) \ - } +#define LSP_NATIVE_METHOD(className, functionName, signature) \ + {#functionName, signature, \ + _NATIVEHELPER_JNI_MACRO_CAST(void *)( \ + Java_org_lsposed_lspd_nativebridge_##className##_##functionName)} #endif -#define JNI_START [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz +#define JNI_START [[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass clazz #ifndef LSP_DEF_NATIVE_METHOD -#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \ - extern "C" ret Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName (JNI_START, ## __VA_ARGS__) +#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \ + extern "C" ret Java_org_lsposed_lspd_nativebridge_##className##_##functionName(JNI_START, \ + ##__VA_ARGS__) #endif -#define REGISTER_LSP_NATIVE_METHODS(class_name) \ - RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, arraysize(gMethods)) +#define REGISTER_LSP_NATIVE_METHODS(class_name) \ + RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, \ + arraysize(gMethods)) -static std::vector> plt_hook_list = {}; -static auto scan_maps = lsplt::MapInfo::Scan(); +static dev_t dev = 0; +static ino_t inode = 0; +static std::vector> plt_hook_saved = {}; -inline int plt_hook(const char *lib, const char *symbol, void *callback, void **backup) { - dev_t dev = 0; - ino_t inode = 0; - for (auto map : scan_maps) { - if (map.path == lib) { - inode = map.inode; - dev = map.dev; - break; +inline int HookArtFunction(void *original, void *callback, void **backup, bool save = true) { + auto symbol = *reinterpret_cast(original); + if (dev == 0 || inode == 0) { + auto libart_path = GetArt()->name(); + for (auto map : lsplt::MapInfo::Scan()) { + if (map.path == libart_path) { + inode = map.inode; + dev = map.dev; + break; + } } } auto result = lsplt::RegisterHook(dev, inode, symbol, callback, backup) && lsplt::CommitHook(); - if (result) { - plt_hook_list.emplace_back(dev, inode, symbol, backup); + if (result && *backup != nullptr) { + if (save) plt_hook_saved.emplace_back(symbol, backup); + } else if (auto addr = GetArt()->getSymbAddress(symbol); addr) { + Dl_info info; + if (dladdr(addr, &info) && info.dli_sname != nullptr && info.dli_sname == symbol) + HookFunction(addr, callback, backup); + } else if (*backup == nullptr && isDebug) { + LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol); + } + return *backup == nullptr; +} + +inline int UnhookArtFunction(void *original) { + std::string_view func_name = *reinterpret_cast(original); + auto hook_iter = std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(), + [func_name](auto record) { return record.first == func_name; }); + + void *stub = nullptr; + if (hook_iter != plt_hook_saved.end() && + HookArtFunction(original, *(hook_iter->second), &stub, false)) { + plt_hook_saved.erase(hook_iter); return 0; } return 1; } -inline int HookFunction(void *original, void *replace, void **backup) { - Dl_info info; - if (dladdr(original, &info)) { - if constexpr (isDebug) { - LOGD("Hooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, - info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); - } - if (info.dli_sname != NULL && info.dli_fname != NULL) - return plt_hook(info.dli_fname, info.dli_sname, replace, backup); - } - return 1; -} - -inline int UnhookFunction(void *original) { - Dl_info info; - if (dladdr(original, &info)) { - if constexpr (isDebug) { - LOGD("Unhooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, - info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); - } - - for (const auto [dev, inode, symbol, backup] : plt_hook_list) { - if (info.dli_sname == symbol) { - auto result = lsplt::RegisterHook(dev, inode, symbol, backup, nullptr) - && lsplt::CommitHook(); - return 1 - result; - } - } - } - return 1; -} - inline std::string GetNativeBridgeSignature() { const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map(); static auto signature = obfs_map.at("org.lsposed.lspd.nativebridge."); return signature; } -} // namespace lspd +} // namespace lspd #pragma clang diagnostic pop diff --git a/core/src/main/jni/src/native_api.cpp b/core/src/main/jni/src/native_api.cpp index 00bd6f6f..d93b9e72 100644 --- a/core/src/main/jni/src/native_api.cpp +++ b/core/src/main/jni/src/native_api.cpp @@ -48,7 +48,6 @@ namespace lspd { - using lsplant::operator""_tstr; std::list moduleLoadedCallbacks; std::list moduleNativeLibs; std::unique_ptr> protected_page( @@ -58,8 +57,8 @@ namespace lspd { const auto[entries] = []() { auto *entries = new(protected_page.get()) NativeAPIEntries{ .version = 2, - .hookFunc = &DobbyHookFunction, - .unhookFunc = &DobbyUnhookFunction, + .hookFunc = &HookFunction, + .unhookFunc = &UnhookFunction, }; mprotect(protected_page.get(), 4096, PROT_READ); @@ -71,7 +70,7 @@ namespace lspd { return InstallNativeAPI({ .inline_hooker = [](auto t, auto r) { void* bk = nullptr; - return DobbyHookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookFunction(t, r, &bk) == 0 ? bk : nullptr; }, }); }(); diff --git a/core/src/main/jni/src/native_api.h b/core/src/main/jni/src/native_api.h index 41b65179..b1203742 100644 --- a/core/src/main/jni/src/native_api.h +++ b/core/src/main/jni/src/native_api.h @@ -52,23 +52,25 @@ namespace lspd { void RegisterNativeLib(const std::string &library_name); - inline int DobbyHookFunction(void *original, void *replace, void **backup) { + inline int HookFunction(void *original, void *replace, void **backup) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) LOGD("Dobby hooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_sname ? info.dli_sname : "(unknown symbol)", + info.dli_saddr ? info.dli_saddr : original, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); } - inline int DobbyUnhookFunction(void *original) { + inline int UnhookFunction(void *original) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) LOGD("Dobby unhooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_sname ? info.dli_sname : "(unknown symbol)", + info.dli_saddr ? info.dli_saddr : original, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } return DobbyDestroy(original); diff --git a/external/lsplant b/external/lsplant index 9ce26897..2009a192 160000 --- a/external/lsplant +++ b/external/lsplant @@ -1 +1 @@ -Subproject commit 9ce26897d3fc9a07ded56b3da612d154c1031a62 +Subproject commit 2009a1922c63e5838eaeff79eacf821d4f6b536f diff --git a/magisk-loader/src/main/jni/src/magisk_loader.cpp b/magisk-loader/src/main/jni/src/magisk_loader.cpp index 72705adf..624241b3 100644 --- a/magisk-loader/src/main/jni/src/magisk_loader.cpp +++ b/magisk-loader/src/main/jni/src/magisk_loader.cpp @@ -119,10 +119,10 @@ namespace lspd { lsplant::InitInfo initInfo{ .inline_hooker = [](auto t, auto r) { void* bk = nullptr; - return HookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr; }, .inline_unhooker = [](auto t) { - return UnhookFunction(t) == 0 ; + return UnhookArtFunction(t) == 0 ; }, .art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); @@ -198,10 +198,10 @@ namespace lspd { lsplant::InitInfo initInfo{ .inline_hooker = [](auto t, auto r) { void* bk = nullptr; - return HookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr; }, .inline_unhooker = [](auto t) { - return UnhookFunction(t) == 0; + return UnhookArtFunction(t) == 0; }, .art_symbol_resolver = [](auto symbol){ return GetArt()->getSymbAddress(symbol);