diff --git a/core/src/main/cpp/main/api/zygisk_main.cpp b/core/src/main/cpp/main/api/zygisk_main.cpp index d6091120..b94d48d7 100644 --- a/core/src/main/cpp/main/api/zygisk_main.cpp +++ b/core/src/main/cpp/main/api/zygisk_main.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "jni/zygisk.h" #include "logging.h" @@ -181,9 +182,9 @@ namespace lspd { return; } - if (int fd; read_int(companion) == 0 && (fd = recv_fd(companion)) != -1) { - Context::GetInstance()->PreLoadDex( - "/proc/self/fd/" + std::to_string(fd)); + if (int fd = -1, size = 0; (size = read_int(companion)) > 0 && + (fd = recv_fd(companion)) != -1) { + Context::GetInstance()->PreLoadDex(fd, size); close(fd); } else { LOGE("Failed to read dex fd"); @@ -211,19 +212,49 @@ namespace lspd { } }; - bool InitCompanion() { - LOGD("onModuleLoaded: welcome to LSPosed!"); - LOGD("onModuleLoaded: version v%s (%d)", versionName, versionCode); - return true; + std::tuple InitCompanion() { + LOGI("onModuleLoaded: welcome to LSPosed!"); + LOGI("onModuleLoaded: version v%s (%d)", versionName, versionCode); + + int (*ashmem_create_region)(const char *name, std::size_t size) = nullptr; + int (*ashmem_set_prot_region)(int fd, int prot) = nullptr; + + std::string path = "/data/adb/modules/"s + lspd::moduleName + "/" + kDexPath; + int fd = open(path.data(), O_RDONLY | O_CLOEXEC); + if (fd < 0) { + LOGE("Failed to load dex: %s", path.data()); + return {-1, 0}; + } + auto fsize = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + auto *cutils = dlopen("/system/lib" LP_SELECT("", "64") "/libcutils.so", 0); + ashmem_create_region = cutils ? reinterpret_cast( + dlsym(cutils, "ashmem_create_region")) : nullptr; + ashmem_set_prot_region = cutils ? reinterpret_cast( + dlsym(cutils, "ashmem_set_prot_region")) : nullptr; + int tmp_fd = -1; + if (void *addr = nullptr; + ashmem_create_region && ashmem_set_prot_region && + (tmp_fd = ashmem_create_region("lspd.dex", fsize)) > 0 && + (addr = mmap(nullptr, fsize, PROT_WRITE, MAP_SHARED, tmp_fd, 0)) && + read(fd, addr, fsize) > 0 && munmap(addr, fsize) == 0) { + LOGD("using memfd"); + ashmem_set_prot_region(tmp_fd, PROT_READ); + std::swap(fd, tmp_fd); + } else { + LOGD("using raw fd"); + } + + close(tmp_fd); + dlclose(cutils); + return {fd, fsize}; } void CompanionEntry(int client) { using namespace std::string_literals; - static bool inited = InitCompanion(); - static std::string path = "/data/adb/modules/"s + lspd::moduleName + "/" + kDexPath; - static int fd = open(path.data(), O_RDONLY | O_CLOEXEC); - if (inited && fd > 0) { - write_int(client, 0); + static auto[fd, size] = InitCompanion(); + if (fd > 0 && size > 0) { + write_int(client, size); send_fd(client, fd); } else write_int(client, -1); close(client); diff --git a/core/src/main/cpp/main/src/context.cpp b/core/src/main/cpp/main/src/context.cpp index 417906fd..c2717eb7 100644 --- a/core/src/main/cpp/main/src/context.cpp +++ b/core/src/main/cpp/main/src/context.cpp @@ -58,11 +58,8 @@ namespace lspd { } } - Context::PreloadedDex::PreloadedDex(FILE *f) { - fseek(f, 0, SEEK_END); - auto size = ftell(f); - rewind(f); - if (auto addr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fileno(f), 0); addr) { + Context::PreloadedDex::PreloadedDex(int fd, std::size_t size) { + if (auto addr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); addr) { addr_ = addr; size_ = size; } else { @@ -74,17 +71,25 @@ namespace lspd { if (*this) munmap(addr_, size_); } + void Context::PreLoadDex(int fd, std::size_t size) { + dex_ = PreloadedDex{fd, size}; + } + void Context::PreLoadDex(std::string_view dex_path) { if (dex_) [[unlikely]] return; std::unique_ptr f{fopen(dex_path.data(), "rb"), &fclose}; - if (!f || !(dex_ = PreloadedDex(f.get()))) { + if (!f) { LOGE("Fail to open dex from %s", dex_path.data()); return; + } else { + fseek(f.get(), 0, SEEK_END); + auto size = ftell(f.get()); + rewind(f.get()); + PreLoadDex(fileno(f.get()), size); } - - LOGI("Loaded %s with size %zu", dex_path.data(), dex_.size()); + LOGD("Loaded %s with size %zu", dex_path.data(), dex_.size()); } void Context::LoadDex(JNIEnv *env) { @@ -272,4 +277,4 @@ namespace lspd { *allowUnload = unload ? 1 : 0; } } -} +} // namespace lspd diff --git a/core/src/main/cpp/main/src/context.h b/core/src/main/cpp/main/src/context.h index d6c0ff55..ea44134d 100644 --- a/core/src/main/cpp/main/src/context.h +++ b/core/src/main/cpp/main/src/context.h @@ -61,6 +61,8 @@ namespace lspd { void PreLoadDex(std::string_view dex_paths); + void PreLoadDex(int fd, std::size_t size); + void Init(); private: @@ -80,6 +82,8 @@ namespace lspd { PreloadedDex &operator=(const PreloadedDex &) = delete; + PreloadedDex(int fd, std::size_t size); + PreloadedDex &operator=(PreloadedDex &&other) { addr_ = other.addr_; size_ = other.size_; @@ -99,8 +103,6 @@ namespace lspd { auto data() const { return addr_; } - PreloadedDex(FILE *f); - ~PreloadedDex(); private: diff --git a/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java b/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java index 654dafe5..7ed2f81e 100644 --- a/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java +++ b/core/src/main/java/org/lsposed/lspd/service/ConfigManager.java @@ -927,9 +927,8 @@ public class ConfigManager { public static List getDenyListPackages() { List result = new ArrayList<>(); - try { - final SQLiteDatabase magiskDb = - SQLiteDatabase.openDatabase(ConfigFileManager.magiskDbPath, new SQLiteDatabase.OpenParams.Builder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build()); + try (final SQLiteDatabase magiskDb = + SQLiteDatabase.openDatabase(ConfigFileManager.magiskDbPath, new SQLiteDatabase.OpenParams.Builder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build())) { try (Cursor cursor = magiskDb.query(true, "denylist", new String[]{"package_name"}, null, null, null, null, null, null, null)) { if (cursor == null) return result; int packageNameIdx = cursor.getColumnIndex("package_name");