Fix CallBooleanMethodV hook of exec_transact (#71)
* Revert "use shared memory" This reverts commit44570c5ed0. * Revert "fix manager not detected" This reverts commit9125b4b2f1. Close #69 as fixed.
This commit is contained in:
parent
89200db966
commit
ff04a68822
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue