Skip to content

Commit

Permalink
use shared memory
Browse files Browse the repository at this point in the history
  • Loading branch information
5ec1cff authored and JingMatrix committed Aug 31, 2024
1 parent c5d7b32 commit 44570c5
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ private static synchronized void sendToBridge(IBinder binder, boolean isRestart)
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();
Expand Down
28 changes: 28 additions & 0 deletions daemon/src/main/java/org/lsposed/lspd/service/ConfigManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
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;
Expand Down Expand Up @@ -91,6 +92,9 @@

public class ConfigManager {
private static ConfigManager instance = null;
private final SharedMemory accessMatrixMemory;
// appid bitmap
private final ByteBuffer accessMatrix;

private final SQLiteDatabase db = openDb();

Expand Down Expand Up @@ -340,6 +344,12 @@ private 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();
Expand Down Expand Up @@ -524,6 +534,13 @@ private synchronized void clearCache() {
}
cachedModule.clear();
cachedScope.clear();
clearAccessMatrix();
}

private void clearAccessMatrix() {
for (var i = 0; i < accessMatrix.capacity(); i++) {
accessMatrix.put(i, (byte) 0);
}
}

private synchronized void cacheModules() {
Expand Down Expand Up @@ -639,6 +656,7 @@ private synchronized void cacheScopes() {
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");
Expand Down Expand Up @@ -732,6 +750,12 @@ private synchronized void cacheScopes() {
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) {
int idx = (appId - 10000) >> 3;
byte bit = (byte) (1 << ((appId - 10000) & 7));
accessMatrix.put(idx, (byte) (accessMatrix.get(idx) | bit));
}
});
}

Expand Down Expand Up @@ -1202,4 +1226,8 @@ public void exportScopes(ZipOutputStream os) throws IOException {
synchronized SharedMemory getPreloadDex() {
return ConfigFileManager.getPreloadDex(dexObfuscate);
}

SharedMemory getAccessMatrixMemory() {
return accessMatrixMemory;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
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;
Expand Down Expand Up @@ -109,6 +111,19 @@ public static boolean onTransact(@NonNull Parcel data, @Nullable Parcel reply, i
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();
}
Expand Down Expand Up @@ -217,4 +232,6 @@ public static boolean execTransact(IBinder obj, int code, long dataObj, long rep
reply.recycle();
}
}

private static native void initializeAccessMatrix(SharedMemory sm);
}
2 changes: 1 addition & 1 deletion magisk-loader/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,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)
target_link_libraries(${PROJECT_NAME} core log android)

if (DEFINED DEBUG_SYMBOLS_PATH)
set(DEBUG_SYMBOLS_PATH ${DEBUG_SYMBOLS_PATH}/${API})
Expand Down
59 changes: 37 additions & 22 deletions magisk-loader/src/main/jni/src/service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,36 @@
#include <dobby.h>
#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"
#include "utils/jni_helper.hpp"
#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>();

std::atomic<uint64_t> last_failed_id = ~0;
uint8_t* access_matrix = nullptr;

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<uint64_t>(uid) << 32) | pid;
uid_t getCallingUid() {
if (getCallingUidFn != nullptr) [[likely]] {
return getCallingUidFn(this);
}
return ~0;
return 0;
}

static IPCThreadState* selfOrNull() {
Expand All @@ -69,17 +70,14 @@ 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"));
LOGI("libbinder selfOrNull {} getCallingPid {} getCallingUid {}", (void*) selfOrNullFn, (void*) getCallingPidFn, (void*) getCallingUidFn);
LOGD("libbinder selfOrNull {} getCallingUid {}", (void*) selfOrNullFn, (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,
Expand All @@ -96,13 +94,6 @@ 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]] {
Expand Down Expand Up @@ -132,9 +123,14 @@ namespace lspd {
va_list args) {
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;
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;
}
}
if (!need_skip && methodId == instance()->exec_transact_backup_methodID_) [[unlikely]] {
jboolean res = false;
Expand All @@ -144,6 +140,19 @@ 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;

Expand Down Expand Up @@ -283,6 +292,12 @@ 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");
}

Expand Down

0 comments on commit 44570c5

Please sign in to comment.