Fix CallBooleanMethodV hook of exec_transact (#71)

* Revert "use shared memory"

This reverts commit 44570c5ed0.

* Revert "fix manager not detected"

This reverts commit 9125b4b2f1.

Close #69 as fixed.
This commit is contained in:
JingMatrix 2024-10-17 18:46:01 +02:00 committed by GitHub
parent 89200db966
commit ff04a68822
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 24 additions and 97 deletions

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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})

View File

@ -23,9 +23,6 @@
#include <thread>
#include <atomic>
#include <android/sharedmem.h>
#include <android/sharedmem_jni.h>
#include <sys/mman.h>
#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> Service::instance_ = std::make_unique<Service>();
uint8_t* access_matrix = nullptr;
std::atomic<uint64_t> 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<uint64_t>(uid) << 32) | pid;
}
return 0;
return ~0;
}
static IPCThreadState* selfOrNull() {
@ -69,14 +68,17 @@ namespace lspd {
}
selfOrNullFn = reinterpret_cast<decltype(selfOrNullFn)>(
binder->getSymbAddress("_ZN7android14IPCThreadState10selfOrNullEv"));
getCallingPidFn = reinterpret_cast<decltype(getCallingPidFn)>(
binder->getSymbAddress("_ZNK7android14IPCThreadState13getCallingPidEv"));
getCallingUidFn = reinterpret_cast<decltype(getCallingUidFn)>(
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<uint8_t*>(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");
}