[core] Use ashmem_create_region (#1304)

This commit is contained in:
LoveSy 2021-10-17 22:18:53 +08:00 committed by GitHub
parent c166163885
commit eeb8aa6ae3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 26 deletions

View File

@ -19,6 +19,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <fcntl.h> #include <fcntl.h>
#include <dlfcn.h>
#include "jni/zygisk.h" #include "jni/zygisk.h"
#include "logging.h" #include "logging.h"
@ -181,9 +182,9 @@ namespace lspd {
return; return;
} }
if (int fd; read_int(companion) == 0 && (fd = recv_fd(companion)) != -1) { if (int fd = -1, size = 0; (size = read_int(companion)) > 0 &&
Context::GetInstance()->PreLoadDex( (fd = recv_fd(companion)) != -1) {
"/proc/self/fd/" + std::to_string(fd)); Context::GetInstance()->PreLoadDex(fd, size);
close(fd); close(fd);
} else { } else {
LOGE("Failed to read dex fd"); LOGE("Failed to read dex fd");
@ -211,19 +212,49 @@ namespace lspd {
} }
}; };
bool InitCompanion() { std::tuple<int, std::size_t> InitCompanion() {
LOGD("onModuleLoaded: welcome to LSPosed!"); LOGI("onModuleLoaded: welcome to LSPosed!");
LOGD("onModuleLoaded: version v%s (%d)", versionName, versionCode); LOGI("onModuleLoaded: version v%s (%d)", versionName, versionCode);
return true;
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<decltype(ashmem_create_region)>(
dlsym(cutils, "ashmem_create_region")) : nullptr;
ashmem_set_prot_region = cutils ? reinterpret_cast<decltype(ashmem_set_prot_region)>(
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) { void CompanionEntry(int client) {
using namespace std::string_literals; using namespace std::string_literals;
static bool inited = InitCompanion(); static auto[fd, size] = InitCompanion();
static std::string path = "/data/adb/modules/"s + lspd::moduleName + "/" + kDexPath; if (fd > 0 && size > 0) {
static int fd = open(path.data(), O_RDONLY | O_CLOEXEC); write_int(client, size);
if (inited && fd > 0) {
write_int(client, 0);
send_fd(client, fd); send_fd(client, fd);
} else write_int(client, -1); } else write_int(client, -1);
close(client); close(client);

View File

@ -58,11 +58,8 @@ namespace lspd {
} }
} }
Context::PreloadedDex::PreloadedDex(FILE *f) { Context::PreloadedDex::PreloadedDex(int fd, std::size_t size) {
fseek(f, 0, SEEK_END); if (auto addr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); addr) {
auto size = ftell(f);
rewind(f);
if (auto addr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fileno(f), 0); addr) {
addr_ = addr; addr_ = addr;
size_ = size; size_ = size;
} else { } else {
@ -74,17 +71,25 @@ namespace lspd {
if (*this) munmap(addr_, size_); 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) { void Context::PreLoadDex(std::string_view dex_path) {
if (dex_) [[unlikely]] return; if (dex_) [[unlikely]] return;
std::unique_ptr<FILE, decltype(&fclose)> f{fopen(dex_path.data(), "rb"), &fclose}; std::unique_ptr<FILE, decltype(&fclose)> 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()); LOGE("Fail to open dex from %s", dex_path.data());
return; return;
} else {
fseek(f.get(), 0, SEEK_END);
auto size = ftell(f.get());
rewind(f.get());
PreLoadDex(fileno(f.get()), size);
} }
LOGD("Loaded %s with size %zu", dex_path.data(), dex_.size());
LOGI("Loaded %s with size %zu", dex_path.data(), dex_.size());
} }
void Context::LoadDex(JNIEnv *env) { void Context::LoadDex(JNIEnv *env) {
@ -272,4 +277,4 @@ namespace lspd {
*allowUnload = unload ? 1 : 0; *allowUnload = unload ? 1 : 0;
} }
} }
} } // namespace lspd

View File

@ -61,6 +61,8 @@ namespace lspd {
void PreLoadDex(std::string_view dex_paths); void PreLoadDex(std::string_view dex_paths);
void PreLoadDex(int fd, std::size_t size);
void Init(); void Init();
private: private:
@ -80,6 +82,8 @@ namespace lspd {
PreloadedDex &operator=(const PreloadedDex &) = delete; PreloadedDex &operator=(const PreloadedDex &) = delete;
PreloadedDex(int fd, std::size_t size);
PreloadedDex &operator=(PreloadedDex &&other) { PreloadedDex &operator=(PreloadedDex &&other) {
addr_ = other.addr_; addr_ = other.addr_;
size_ = other.size_; size_ = other.size_;
@ -99,8 +103,6 @@ namespace lspd {
auto data() const { return addr_; } auto data() const { return addr_; }
PreloadedDex(FILE *f);
~PreloadedDex(); ~PreloadedDex();
private: private:

View File

@ -927,9 +927,8 @@ public class ConfigManager {
public static List<String> getDenyListPackages() { public static List<String> getDenyListPackages() {
List<String> result = new ArrayList<>(); List<String> result = new ArrayList<>();
try { try (final SQLiteDatabase magiskDb =
final SQLiteDatabase magiskDb = SQLiteDatabase.openDatabase(ConfigFileManager.magiskDbPath, new SQLiteDatabase.OpenParams.Builder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build())) {
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)) { try (Cursor cursor = magiskDb.query(true, "denylist", new String[]{"package_name"}, null, null, null, null, null, null, null)) {
if (cursor == null) return result; if (cursor == null) return result;
int packageNameIdx = cursor.getColumnIndex("package_name"); int packageNameIdx = cursor.getColumnIndex("package_name");