mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 21:37:38 +00:00
Add new Zygisk API to get module dir
This commit is contained in:
parent
d7b51d2807
commit
21d7db0959
@ -541,15 +541,7 @@ static void inject_magisk_bins(root_node *system) {
|
|||||||
delete bin->extract(init_applet[i]);
|
delete bin->extract(init_applet[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct module_info {
|
vector<module_info> *module_list;
|
||||||
string name;
|
|
||||||
int z32 = -1;
|
|
||||||
#if defined(__LP64__)
|
|
||||||
int z64 = -1;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static vector<module_info> *modules;
|
|
||||||
int app_process_32 = -1;
|
int app_process_32 = -1;
|
||||||
int app_process_64 = -1;
|
int app_process_64 = -1;
|
||||||
|
|
||||||
@ -577,8 +569,8 @@ void magic_mount() {
|
|||||||
|
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
LOGI("* Loading modules\n");
|
LOGI("* Loading modules\n");
|
||||||
if (modules) {
|
if (module_list) {
|
||||||
for (const auto &m : *modules) {
|
for (const auto &m : *module_list) {
|
||||||
const char *module = m.name.data();
|
const char *module = m.name.data();
|
||||||
char *b = buf + sprintf(buf, "%s/" MODULEMNT "/%s/", MAGISKTMP.data(), module);
|
char *b = buf + sprintf(buf, "%s/" MODULEMNT "/%s/", MAGISKTMP.data(), module);
|
||||||
|
|
||||||
@ -732,7 +724,7 @@ static void collect_modules(bool open_zygisk) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.name = entry->d_name;
|
info.name = entry->d_name;
|
||||||
modules->push_back(info);
|
module_list->push_back(info);
|
||||||
});
|
});
|
||||||
if (open_zygisk && zygisk_enabled) {
|
if (open_zygisk && zygisk_enabled) {
|
||||||
bool use_memfd = true;
|
bool use_memfd = true;
|
||||||
@ -752,7 +744,7 @@ static void collect_modules(bool open_zygisk) {
|
|||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
};
|
};
|
||||||
std::for_each(modules->begin(), modules->end(), [&](module_info &info) {
|
std::for_each(module_list->begin(), module_list->end(), [&](module_info &info) {
|
||||||
info.z32 = convert_to_memfd(info.z32);
|
info.z32 = convert_to_memfd(info.z32);
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
info.z64 = convert_to_memfd(info.z64);
|
info.z64 = convert_to_memfd(info.z64);
|
||||||
@ -762,13 +754,13 @@ static void collect_modules(bool open_zygisk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handle_modules() {
|
void handle_modules() {
|
||||||
default_new(modules);
|
default_new(module_list);
|
||||||
prepare_modules();
|
prepare_modules();
|
||||||
collect_modules(false);
|
collect_modules(false);
|
||||||
exec_module_scripts("post-fs-data");
|
exec_module_scripts("post-fs-data");
|
||||||
|
|
||||||
// Recollect modules (module scripts could remove itself)
|
// Recollect modules (module scripts could remove itself)
|
||||||
modules->clear();
|
module_list->clear();
|
||||||
collect_modules(true);
|
collect_modules(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,24 +781,7 @@ void remove_modules() {
|
|||||||
|
|
||||||
void exec_module_scripts(const char *stage) {
|
void exec_module_scripts(const char *stage) {
|
||||||
vector<string_view> module_names;
|
vector<string_view> module_names;
|
||||||
std::transform(modules->begin(), modules->end(), std::back_inserter(module_names),
|
std::transform(module_list->begin(), module_list->end(), std::back_inserter(module_names),
|
||||||
[](const module_info &info) -> string_view { return info.name; });
|
[](const module_info &info) -> string_view { return info.name; });
|
||||||
exec_module_scripts(stage, module_names);
|
exec_module_scripts(stage, module_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> zygisk_module_fds(bool is_64_bit) {
|
|
||||||
vector<int> fds;
|
|
||||||
// All fds passed to send_fds have to be valid file descriptors.
|
|
||||||
// To workaround this issue, send over STDOUT_FILENO as an indicator of an
|
|
||||||
// invalid fd as it will always be /dev/null in magiskd
|
|
||||||
if (is_64_bit) {
|
|
||||||
#if defined(__LP64__)
|
|
||||||
std::transform(modules->begin(), modules->end(), std::back_inserter(fds),
|
|
||||||
[](const module_info &info) { return info.z64 < 0 ? STDOUT_FILENO : info.z64; });
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
std::transform(modules->begin(), modules->end(), std::back_inserter(fds),
|
|
||||||
[](const module_info &info) { return info.z32 < 0 ? STDOUT_FILENO : info.z32; });
|
|
||||||
}
|
|
||||||
return fds;
|
|
||||||
}
|
|
||||||
|
@ -42,9 +42,18 @@ enum : int {
|
|||||||
DAEMON_LAST
|
DAEMON_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct module_info {
|
||||||
|
std::string name;
|
||||||
|
int z32 = -1;
|
||||||
|
#if defined(__LP64__)
|
||||||
|
int z64 = -1;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
extern bool zygisk_enabled;
|
extern bool zygisk_enabled;
|
||||||
extern int app_process_32;
|
extern int app_process_32;
|
||||||
extern int app_process_64;
|
extern int app_process_64;
|
||||||
|
extern std::vector<module_info> *module_list;
|
||||||
|
|
||||||
int connect_daemon(bool create = false);
|
int connect_daemon(bool create = false);
|
||||||
|
|
||||||
@ -69,7 +78,6 @@ void boot_complete(int client);
|
|||||||
void denylist_handler(int client, const sock_cred *cred);
|
void denylist_handler(int client, const sock_cred *cred);
|
||||||
void su_daemon_handler(int client, const sock_cred *cred);
|
void su_daemon_handler(int client, const sock_cred *cred);
|
||||||
void zygisk_handler(int client, const sock_cred *cred);
|
void zygisk_handler(int client, const sock_cred *cred);
|
||||||
std::vector<int> zygisk_module_fds(bool is_64_bit);
|
|
||||||
|
|
||||||
// Denylist
|
// Denylist
|
||||||
void initialize_denylist();
|
void initialize_denylist();
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#define ZYGISK_API_VERSION 1
|
#define ZYGISK_API_VERSION 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -173,6 +173,16 @@ struct Api {
|
|||||||
// module's companion request handler. Returns -1 if the connection attempt failed.
|
// module's companion request handler. Returns -1 if the connection attempt failed.
|
||||||
int connectCompanion();
|
int connectCompanion();
|
||||||
|
|
||||||
|
// Get the file descriptor of the root folder of the current module.
|
||||||
|
//
|
||||||
|
// This API only works in the pre[XXX]Specialize functions.
|
||||||
|
// Accessing the directory returned is only possible in the pre[XXX]Specialize functions
|
||||||
|
// or in the root companion process (assuming that you sent the fd over the socket).
|
||||||
|
// Both restrictions are due to SELinux and UID.
|
||||||
|
//
|
||||||
|
// Returns -1 if errors occurred.
|
||||||
|
int getModuleDir();
|
||||||
|
|
||||||
// Set various options for your module.
|
// Set various options for your module.
|
||||||
// Please note that this function accepts one single option at a time.
|
// Please note that this function accepts one single option at a time.
|
||||||
// Check zygisk::Option for the full list of options available.
|
// Check zygisk::Option for the full list of options available.
|
||||||
@ -261,6 +271,7 @@ struct api_table {
|
|||||||
// Zygisk functions
|
// Zygisk functions
|
||||||
int (*connectCompanion)(void * /* _this */);
|
int (*connectCompanion)(void * /* _this */);
|
||||||
void (*setOption)(void * /* _this */, Option);
|
void (*setOption)(void * /* _this */, Option);
|
||||||
|
int (*getModuleDir)(void * /* _this */);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -278,6 +289,9 @@ void entry_impl(api_table *table, JNIEnv *env) {
|
|||||||
inline int Api::connectCompanion() {
|
inline int Api::connectCompanion() {
|
||||||
return impl->connectCompanion ? impl->connectCompanion(impl->_this) : -1;
|
return impl->connectCompanion ? impl->connectCompanion(impl->_this) : -1;
|
||||||
}
|
}
|
||||||
|
inline int Api::getModuleDir() {
|
||||||
|
return impl->getModuleDir ? impl->getModuleDir(impl->_this) : -1;
|
||||||
|
}
|
||||||
inline void Api::setOption(Option opt) {
|
inline void Api::setOption(Option opt) {
|
||||||
if (impl->setOption) impl->setOption(impl->_this, opt);
|
if (impl->setOption) impl->setOption(impl->_this, opt);
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,23 @@ std::vector<int> remote_get_info(int uid, const char *process, AppInfo *info) {
|
|||||||
|
|
||||||
// The following code runs in magiskd
|
// The following code runs in magiskd
|
||||||
|
|
||||||
|
static vector<int> get_module_fds(bool is_64_bit) {
|
||||||
|
vector<int> fds;
|
||||||
|
// All fds passed to send_fds have to be valid file descriptors.
|
||||||
|
// To workaround this issue, send over STDOUT_FILENO as an indicator of an
|
||||||
|
// invalid fd as it will always be /dev/null in magiskd
|
||||||
|
if (is_64_bit) {
|
||||||
|
#if defined(__LP64__)
|
||||||
|
std::transform(module_list->begin(), module_list->end(), std::back_inserter(fds),
|
||||||
|
[](const module_info &info) { return info.z64 < 0 ? STDOUT_FILENO : info.z64; });
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
std::transform(module_list->begin(), module_list->end(), std::back_inserter(fds),
|
||||||
|
[](const module_info &info) { return info.z32 < 0 ? STDOUT_FILENO : info.z32; });
|
||||||
|
}
|
||||||
|
return fds;
|
||||||
|
}
|
||||||
|
|
||||||
static bool get_exe(int pid, char *buf, size_t sz) {
|
static bool get_exe(int pid, char *buf, size_t sz) {
|
||||||
snprintf(buf, sz, "/proc/%d/exe", pid);
|
snprintf(buf, sz, "/proc/%d/exe", pid);
|
||||||
return xreadlink(buf, buf, sz) > 0;
|
return xreadlink(buf, buf, sz) > 0;
|
||||||
@ -221,7 +238,7 @@ static void connect_companion(int client, bool is_64_bit) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
vector<int> module_fds = zygisk_module_fds(is_64_bit);
|
vector<int> module_fds = get_module_fds(is_64_bit);
|
||||||
send_fds(zygiskd_socket, module_fds.data(), module_fds.size());
|
send_fds(zygiskd_socket, module_fds.data(), module_fds.size());
|
||||||
// Wait for ack
|
// Wait for ack
|
||||||
if (read_int(zygiskd_socket) != 0) {
|
if (read_int(zygiskd_socket) != 0) {
|
||||||
@ -342,7 +359,7 @@ static void get_process_info(int client, const sock_cred *cred) {
|
|||||||
if (!info.on_denylist) {
|
if (!info.on_denylist) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
get_exe(cred->pid, buf, sizeof(buf));
|
get_exe(cred->pid, buf, sizeof(buf));
|
||||||
vector<int> fds = zygisk_module_fds(str_ends(buf, "64"));
|
vector<int> fds = get_module_fds(str_ends(buf, "64"));
|
||||||
send_fds(client, fds.data(), fds.size());
|
send_fds(client, fds.data(), fds.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,6 +374,15 @@ static void send_log_pipe(int fd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void get_moddir(int client) {
|
||||||
|
int id = read_int(client);
|
||||||
|
char buf[4096];
|
||||||
|
snprintf(buf, sizeof(buf), MODULEROOT "/%s", module_list->operator[](id).name.data());
|
||||||
|
int dfd = xopen(buf, O_RDONLY | O_CLOEXEC);
|
||||||
|
send_fd(client, dfd);
|
||||||
|
close(dfd);
|
||||||
|
}
|
||||||
|
|
||||||
void zygisk_handler(int client, const sock_cred *cred) {
|
void zygisk_handler(int client, const sock_cred *cred) {
|
||||||
int code = read_int(client);
|
int code = read_int(client);
|
||||||
char buf[256];
|
char buf[256];
|
||||||
@ -377,6 +403,9 @@ void zygisk_handler(int client, const sock_cred *cred) {
|
|||||||
get_exe(cred->pid, buf, sizeof(buf));
|
get_exe(cred->pid, buf, sizeof(buf));
|
||||||
connect_companion(client, str_ends(buf, "64"));
|
connect_companion(client, str_ends(buf, "64"));
|
||||||
break;
|
break;
|
||||||
|
case ZYGISK_GET_MODDIR:
|
||||||
|
get_moddir(client);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
@ -294,16 +294,26 @@ bool ZygiskModule::RegisterModule(ApiTable *table, long *module) {
|
|||||||
table->module->ver = module;
|
table->module->ver = module;
|
||||||
|
|
||||||
// Fill in API accordingly with module API version
|
// Fill in API accordingly with module API version
|
||||||
|
switch (ver) {
|
||||||
|
case 2:
|
||||||
|
table->v2.getModuleDir = [](ZygiskModule *m) { return m->getModuleDir(); };
|
||||||
|
[[fallthrough]];
|
||||||
|
case 1:
|
||||||
table->v1.hookJniNativeMethods = &hookJniNativeMethods;
|
table->v1.hookJniNativeMethods = &hookJniNativeMethods;
|
||||||
table->v1.pltHookRegister = [](const char *path, const char *symbol, void *n, void **o) {
|
table->v1.pltHookRegister = [](const char *p, const char *s, void *n, void **o) {
|
||||||
xhook_register(path, symbol, n, o);
|
xhook_register(p, s, n, o);
|
||||||
};
|
};
|
||||||
table->v1.pltHookExclude = [](const char *path, const char *symbol) {
|
table->v1.pltHookExclude = [](const char *p, const char *s) {
|
||||||
xhook_ignore(path, symbol);
|
xhook_ignore(p, s);
|
||||||
};
|
};
|
||||||
table->v1.pltHookCommit = []{ bool r = xhook_refresh(0) == 0; xhook_clear(); return r; };
|
table->v1.pltHookCommit = []{ bool r = xhook_refresh(0) == 0; xhook_clear(); return r; };
|
||||||
table->v1.connectCompanion = [](ZygiskModule *m) { return m->connectCompanion(); };
|
table->v1.connectCompanion = [](ZygiskModule *m) { return m->connectCompanion(); };
|
||||||
table->v1.setOption = [](ZygiskModule *m, auto opt) { m->setOption(opt); };
|
table->v1.setOption = [](ZygiskModule *m, auto opt) { m->setOption(opt); };
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown version number
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -318,6 +328,18 @@ int ZygiskModule::connectCompanion() const {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ZygiskModule::getModuleDir() const {
|
||||||
|
if (int fd = connect_daemon(); fd >= 0) {
|
||||||
|
write_int(fd, ZYGISK_REQUEST);
|
||||||
|
write_int(fd, ZYGISK_GET_MODDIR);
|
||||||
|
write_int(fd, id);
|
||||||
|
int dfd = recv_fd(fd);
|
||||||
|
close(fd);
|
||||||
|
return dfd;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void ZygiskModule::setOption(zygisk::Option opt) {
|
void ZygiskModule::setOption(zygisk::Option opt) {
|
||||||
if (g_ctx == nullptr)
|
if (g_ctx == nullptr)
|
||||||
return;
|
return;
|
||||||
|
@ -81,6 +81,9 @@ struct ApiTable {
|
|||||||
int (*connectCompanion)(ZygiskModule *);
|
int (*connectCompanion)(ZygiskModule *);
|
||||||
void (*setOption)(ZygiskModule *, zygisk::Option);
|
void (*setOption)(ZygiskModule *, zygisk::Option);
|
||||||
} v1;
|
} v1;
|
||||||
|
struct {
|
||||||
|
int (*getModuleDir)(ZygiskModule *);
|
||||||
|
} v2;
|
||||||
|
|
||||||
ApiTable(ZygiskModule *m);
|
ApiTable(ZygiskModule *m);
|
||||||
};
|
};
|
||||||
@ -100,6 +103,7 @@ struct ZygiskModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int connectCompanion() const;
|
int connectCompanion() const;
|
||||||
|
int getModuleDir() const;
|
||||||
void setOption(zygisk::Option opt);
|
void setOption(zygisk::Option opt);
|
||||||
void doUnload() const { if (unload) dlclose(handle); }
|
void doUnload() const { if (unload) dlclose(handle); }
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ enum : int {
|
|||||||
ZYGISK_GET_INFO,
|
ZYGISK_GET_INFO,
|
||||||
ZYGISK_GET_LOG_PIPE,
|
ZYGISK_GET_LOG_PIPE,
|
||||||
ZYGISK_CONNECT_COMPANION,
|
ZYGISK_CONNECT_COMPANION,
|
||||||
|
ZYGISK_GET_MODDIR,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user