From ff04a688222c18b154311cde344d312de6f53cce Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Thu, 17 Oct 2024 18:46:01 +0200 Subject: [PATCH] Fix CallBooleanMethodV hook of exec_transact (#71) * Revert "use shared memory" This reverts commit 44570c5ed0fd9d953b9d10cec35d5c723fb3e0b8. * Revert "fix manager not detected" This reverts commit 9125b4b2f1439e058fa516a3835edbaa3c561b1c. Close #69 as fixed. --- .../lsposed/lspd/service/BridgeService.java | 1 - .../lsposed/lspd/service/ConfigManager.java | 42 +------------ .../lsposed/lspd/service/BridgeService.java | 17 ------ magisk-loader/src/main/jni/CMakeLists.txt | 2 +- magisk-loader/src/main/jni/src/service.cpp | 59 +++++++------------ 5 files changed, 24 insertions(+), 97 deletions(-) diff --git a/daemon/src/main/java/org/lsposed/lspd/service/BridgeService.java b/daemon/src/main/java/org/lsposed/lspd/service/BridgeService.java index 22c0e050..8dc68741 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/BridgeService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/BridgeService.java @@ -136,7 +136,6 @@ public class BridgeService { data.writeInt(ACTION.ACTION_SEND_BINDER.ordinal()); Log.v(TAG, "binder " + binder.toString()); data.writeStrongBinder(binder); - data.writeParcelable(ConfigManager.getInstance().getAccessMatrixMemory(), 0); if (bridgeService == null) break; res = bridgeService.transact(TRANSACTION_CODE, data, reply, 0); reply.readException(); diff --git a/daemon/src/main/java/org/lsposed/lspd/service/ConfigManager.java b/daemon/src/main/java/org/lsposed/lspd/service/ConfigManager.java index 34ea4ce2..77b8ee94 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/ConfigManager.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/ConfigManager.java @@ -60,7 +60,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -92,9 +91,6 @@ import hidden.HiddenApiBridge; public class ConfigManager { private static ConfigManager instance = null; - private final SharedMemory accessMatrixMemory; - // appid bitmap - private final ByteBuffer accessMatrix; private final SQLiteDatabase db = openDb(); @@ -312,15 +308,14 @@ public class ConfigManager { public synchronized void updateManager(boolean uninstalled) { if (uninstalled) { - setAccessMatrixAppId(managerUid, false); managerUid = -1; + return; } if (!PackageService.isAlive()) return; try { PackageInfo info = PackageService.getPackageInfo(BuildConfig.DEFAULT_MANAGER_PACKAGE_NAME, 0, 0); if (info != null) { managerUid = info.applicationInfo.uid; - setAccessMatrixAppId(managerUid, true); } else { managerUid = -1; Log.i(TAG, "manager is not installed"); @@ -351,12 +346,6 @@ public class ConfigManager { HandlerThread cacheThread = new HandlerThread("cache"); cacheThread.start(); cacheHandler = new Handler(cacheThread.getLooper()); - try { - accessMatrixMemory = SharedMemory.create("access", 1250); - accessMatrix = accessMatrixMemory.mapReadWrite(); - } catch (ErrnoException e) { - throw new RuntimeException(e); - } initDB(); updateConfig(); @@ -541,23 +530,6 @@ public class ConfigManager { } cachedModule.clear(); cachedScope.clear(); - clearAccessMatrix(); - } - - private synchronized void clearAccessMatrix() { - for (var i = 0; i < accessMatrix.capacity(); i++) { - accessMatrix.put(i, (byte) 0); - } - } - - private synchronized void setAccessMatrixAppId(int appId, boolean set) { - if (appId < 10000 || appId > 19999) return; - int idx = (appId - 10000) >> 3; - byte bit = (byte) (1 << ((appId - 10000) & 7)); - if (set) - accessMatrix.put(idx, (byte) (accessMatrix.get(idx) | bit)); - else - accessMatrix.put(idx, (byte) (accessMatrix.get(idx) & ~bit)); } private synchronized void cacheModules() { @@ -673,7 +645,6 @@ public class ConfigManager { else lastScopeCacheTime = SystemClock.elapsedRealtime(); } cachedScope.clear(); - clearAccessMatrix(); try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"app_pkg_name", "module_pkg_name", "user_id"}, "enabled = 1", null, null, null, null)) { int appPkgNameIdx = cursor.getColumnIndex("app_pkg_name"); @@ -767,14 +738,7 @@ public class ConfigManager { cachedScope.forEach((ps, modules) -> { Log.d(TAG, ps.processName + "/" + ps.uid); modules.forEach(module -> Log.d(TAG, "\t" + module.packageName)); - var appId = ps.uid % PER_USER_RANGE; - if (appId >= 10000 && appId <= 19999) { - setAccessMatrixAppId(appId, true); - } }); - if (managerUid != -1) { - setAccessMatrixAppId(managerUid, true); - } } // This is called when a new process created, use the cached result @@ -1259,8 +1223,4 @@ public class ConfigManager { synchronized SharedMemory getPreloadDex() { return ConfigFileManager.getPreloadDex(dexObfuscate); } - - SharedMemory getAccessMatrixMemory() { - return accessMatrixMemory; - } } diff --git a/magisk-loader/src/main/java/org/lsposed/lspd/service/BridgeService.java b/magisk-loader/src/main/java/org/lsposed/lspd/service/BridgeService.java index d7f6d3ca..9391d886 100644 --- a/magisk-loader/src/main/java/org/lsposed/lspd/service/BridgeService.java +++ b/magisk-loader/src/main/java/org/lsposed/lspd/service/BridgeService.java @@ -26,11 +26,9 @@ import android.app.ActivityThread; import android.app.IApplicationThread; import android.content.Context; import android.os.Binder; -import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; -import android.os.SharedMemory; import android.util.Log; import androidx.annotation.NonNull; @@ -112,19 +110,6 @@ public class BridgeService { case ACTION_SEND_BINDER: { if (Binder.getCallingUid() == 0) { receiveFromBridge(data.readStrongBinder()); - try { - SharedMemory sm; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - sm = data.readParcelable(ClassLoader.getSystemClassLoader(), SharedMemory.class); - } else { - sm = data.readParcelable(ClassLoader.getSystemClassLoader()); - } - assert sm != null; - initializeAccessMatrix(sm); - sm.close(); - } catch (Throwable t) { - Log.e(TAG, "initialize shared memory", t); - } if (reply != null) { reply.writeNoException(); } @@ -196,6 +181,4 @@ public class BridgeService { reply.recycle(); } } - - private static native void initializeAccessMatrix(SharedMemory sm); } diff --git a/magisk-loader/src/main/jni/CMakeLists.txt b/magisk-loader/src/main/jni/CMakeLists.txt index 5ab81a6c..c550ef65 100644 --- a/magisk-loader/src/main/jni/CMakeLists.txt +++ b/magisk-loader/src/main/jni/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(${PROJECT_NAME} SHARED ${SRC_LIST} ${CMAKE_CURRENT_BINARY_DIR}/src/l target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PRIVATE src) -target_link_libraries(${PROJECT_NAME} core log android) +target_link_libraries(${PROJECT_NAME} core log) if (DEFINED DEBUG_SYMBOLS_PATH) set(DEBUG_SYMBOLS_PATH ${DEBUG_SYMBOLS_PATH}/${API}) diff --git a/magisk-loader/src/main/jni/src/service.cpp b/magisk-loader/src/main/jni/src/service.cpp index a129a172..45c46271 100644 --- a/magisk-loader/src/main/jni/src/service.cpp +++ b/magisk-loader/src/main/jni/src/service.cpp @@ -23,9 +23,6 @@ #include #include -#include -#include -#include #include "loader.h" #include "service.h" #include "context.h" @@ -33,26 +30,28 @@ #include "symbol_cache.h" #include "config_bridge.h" #include "elf_util.h" -#include "native_util.h" using namespace lsplant; namespace lspd { std::unique_ptr Service::instance_ = std::make_unique(); - uint8_t* access_matrix = nullptr; + std::atomic last_failed_id = ~0; class IPCThreadState { static IPCThreadState* (*selfOrNullFn)(); + static pid_t (*getCallingPidFn)(IPCThreadState*); static uid_t (*getCallingUidFn)(IPCThreadState*); public: - uid_t getCallingUid() { - if (getCallingUidFn != nullptr) [[likely]] { - return getCallingUidFn(this); + 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; + return ~0; } static IPCThreadState* selfOrNull() { @@ -69,14 +68,17 @@ namespace lspd { } selfOrNullFn = reinterpret_cast( binder->getSymbAddress("_ZN7android14IPCThreadState10selfOrNullEv")); + getCallingPidFn = reinterpret_cast( + binder->getSymbAddress("_ZNK7android14IPCThreadState13getCallingPidEv")); getCallingUidFn = reinterpret_cast( binder->getSymbAddress("_ZNK7android14IPCThreadState13getCallingUidEv")); - LOGD("libbinder selfOrNull {} getCallingUid {}", (void*) selfOrNullFn, (void*) getCallingUidFn); + 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, @@ -93,6 +95,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; } return false; @@ -103,14 +112,9 @@ namespace lspd { va_list args) { bool need_skip = false; if (auto self = IPCThreadState::selfOrNull(); self != nullptr) { - auto uid = self->getCallingUid(); - auto appId = uid % 100000; - if (appId >= 10000 && appId <= 19999 && access_matrix != nullptr) { - need_skip = (access_matrix[(appId - 10000) >> 3] & (1 << ((appId - 10000) & 7))) == 0; - } else { - // isolated - need_skip = appId >= 90000 && appId <= 99999; - } + 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; @@ -120,19 +124,6 @@ namespace lspd { return instance()->call_boolean_method_va_backup_(env, obj, methodId, args); } - LSP_DEF_NATIVE_METHOD(void, BridgeService, initializeAccessMatrix, jobject shared_memory) { - if (access_matrix != nullptr) return; - auto fd = ASharedMemory_dupFromJava(env, shared_memory); - auto addr = mmap(nullptr, 1250, PROT_READ, MAP_SHARED, fd, 0); - if (addr == MAP_FAILED) { - PLOGE("map access matrix"); - } else { - LOGD("access matrix at {}", addr); - access_matrix = reinterpret_cast(addr); - } - close(fd); - } - void Service::InitService(JNIEnv *env) { if (initialized_) [[unlikely]] return; @@ -257,12 +248,6 @@ namespace lspd { IPCThreadState::Init(binder.get()); lspd::GetLibBinder(true); - JNINativeMethod m[] = { - LSP_NATIVE_METHOD(BridgeService, initializeAccessMatrix, "(Landroid/os/SharedMemory;)V") - }; - - JNI_RegisterNatives(env, bridge_service_class_, m, 1); - LOGD("Done InitService"); }