From c5d7b32cc01c1829cf3932866f5dd09e38999e99 Mon Sep 17 00:00:00 2001 From: 5ec1cff Date: Wed, 24 Jan 2024 23:31:47 +0800 Subject: [PATCH] ignore binder transactions flooding --- core/src/main/jni/include/config.h | 6 +- core/src/main/jni/include/symbol_cache.h | 2 + core/src/main/jni/src/symbol_cache.cpp | 20 +++++++ magisk-loader/src/main/jni/src/service.cpp | 64 +++++++++++++++++++++- 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/core/src/main/jni/include/config.h b/core/src/main/jni/include/config.h index 4c5eff54..1a91e325 100644 --- a/core/src/main/jni/include/config.h +++ b/core/src/main/jni/include/config.h @@ -59,8 +59,10 @@ namespace lspd { # define LP_SELECT(lp32, lp64) lp32 #endif - inline static constexpr auto kLibArtName = "libart.so"_tstr; - inline static constexpr auto kLibFwName = "libandroidfw.so"_tstr; + inline static constexpr auto kLibArtName = "libart.so"; + inline static constexpr auto kLibBinderName = "libbinder.so"; + inline static constexpr auto kLibFwName = "libandroidfw.so"; + inline static constexpr auto kLinkerName = "/linker"; inline constexpr const char *BoolToString(bool b) { return b ? "true" : "false"; diff --git a/core/src/main/jni/include/symbol_cache.h b/core/src/main/jni/include/symbol_cache.h index e4d2f0e4..fae57f88 100644 --- a/core/src/main/jni/include/symbol_cache.h +++ b/core/src/main/jni/include/symbol_cache.h @@ -33,6 +33,8 @@ namespace SandHook { namespace lspd { std::unique_ptr &GetArt(bool release=false); + std::unique_ptr &GetLibBinder(bool release=false); + std::unique_ptr &GetLinker(bool release=false); } #endif //LSPOSED_SYMBOL_CACHE_H diff --git a/core/src/main/jni/src/symbol_cache.cpp b/core/src/main/jni/src/symbol_cache.cpp index 552ae38f..4c35d018 100644 --- a/core/src/main/jni/src/symbol_cache.cpp +++ b/core/src/main/jni/src/symbol_cache.cpp @@ -40,4 +40,24 @@ namespace lspd { } return kArtImg; } + + std::unique_ptr &GetLibBinder(bool release) { + static std::unique_ptr kImg = nullptr; + if (release) { + kImg.reset(); + } else if (!kImg) { + kImg = std::make_unique(kLibBinderName); + } + return kImg; + } + + std::unique_ptr &GetLinker(bool release) { + static std::unique_ptr kImg = nullptr; + if (release) { + kImg.reset(); + } else if (!kImg) { + kImg = std::make_unique(kLinkerName); + } + return kImg; + } } // namespace lspd diff --git a/magisk-loader/src/main/jni/src/service.cpp b/magisk-loader/src/main/jni/src/service.cpp index 6027c734..9db0fb3a 100644 --- a/magisk-loader/src/main/jni/src/service.cpp +++ b/magisk-loader/src/main/jni/src/service.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "loader.h" #include "service.h" #include "context.h" @@ -36,6 +37,50 @@ using namespace lsplant; namespace lspd { std::unique_ptr Service::instance_ = std::make_unique(); + std::atomic last_failed_id = ~0; + + class IPCThreadState { + static IPCThreadState* (*selfOrNullFn)(); + static pid_t (*getCallingPidFn)(IPCThreadState*); + static uid_t (*getCallingUidFn)(IPCThreadState*); + + public: + + uint64_t getCallingId() { + if (getCallingUidFn != nullptr && getCallingPidFn != nullptr) [[likely]] { + auto pid = getCallingUidFn(this); + auto uid = getCallingPidFn(this); + return (static_cast(uid) << 32) | pid; + } + return ~0; + } + + static IPCThreadState* selfOrNull() { + if (selfOrNullFn != nullptr) [[likely]] { + return selfOrNullFn(); + } + return nullptr; + } + + static void Init(const SandHook::ElfImg *binder) { + if (binder == nullptr) { + LOGE("libbinder not found"); + return; + } + selfOrNullFn = reinterpret_cast( + binder->getSymbAddress("_ZN7android14IPCThreadState10selfOrNullEv")); + getCallingPidFn = reinterpret_cast( + binder->getSymbAddress("_ZNK7android14IPCThreadState13getCallingPidEv")); + getCallingUidFn = reinterpret_cast( + binder->getSymbAddress("_ZNK7android14IPCThreadState13getCallingUidEv")); + LOGI("libbinder selfOrNull {} getCallingPid {} getCallingUid {}", (void*) selfOrNullFn, (void*) getCallingPidFn, (void*) getCallingUidFn); + } + }; + + IPCThreadState* (*IPCThreadState::selfOrNullFn)() = nullptr; + uid_t (*IPCThreadState::getCallingUidFn)(IPCThreadState*) = nullptr; + pid_t (*IPCThreadState::getCallingPidFn)(IPCThreadState*) = nullptr; + jboolean Service::exec_transact_replace(jboolean *res, JNIEnv *env, [[maybe_unused]] jobject obj, va_list args) { @@ -51,6 +96,13 @@ namespace lspd { *res = JNI_CallStaticBooleanMethod(env, instance()->bridge_service_class_, instance()->exec_transact_replace_methodID_, obj, code, data_obj, reply_obj, flags); + if (!*res) { + auto self = IPCThreadState::selfOrNull(); + if (self != nullptr) { + auto id = self->getCallingId(); + last_failed_id.store(id, std::memory_order_relaxed); + } + } return true; } else if (SET_ACTIVITY_CONTROLLER_CODE != -1 && code == SET_ACTIVITY_CONTROLLER_CODE) [[unlikely]] { @@ -78,7 +130,13 @@ namespace lspd { jboolean Service::call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId, va_list args) { - if (methodId == instance()->exec_transact_backup_methodID_) [[unlikely]] { + bool need_skip = false; + if (auto self = IPCThreadState::selfOrNull(); self != nullptr) { + auto last = last_failed_id.load(std::memory_order_relaxed); + auto current = self->getCallingId(); + need_skip = last == current; + } + if (!need_skip && methodId == instance()->exec_transact_backup_methodID_) [[unlikely]] { jboolean res = false; if (exec_transact_replace(&res, env, obj, args)) [[unlikely]] return res; // else fallback to backup @@ -221,6 +279,10 @@ namespace lspd { } } + auto &binder = lspd::GetLibBinder(false); + IPCThreadState::Init(binder.get()); + lspd::GetLibBinder(true); + LOGD("Done InitService"); }