mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-16 16:51:23 +00:00
Load Zygisk modules
This commit is contained in:
@@ -31,6 +31,6 @@ void exec_module_scripts(const char *stage);
|
||||
// Scripting
|
||||
void exec_script(const char *script);
|
||||
void exec_common_scripts(const char *stage);
|
||||
void exec_module_scripts(const char *stage, const std::vector<std::string> &module_list);
|
||||
void exec_module_scripts(const char *stage, const std::vector<std::string_view> &modules);
|
||||
void install_apk(const char *apk);
|
||||
[[noreturn]] void install_module(const char *file);
|
||||
|
@@ -22,8 +22,6 @@ using namespace std;
|
||||
#define TYPE_CUSTOM (1 << 5) /* custom node type overrides all */
|
||||
#define TYPE_DIR (TYPE_INTER|TYPE_TMPFS|TYPE_ROOT)
|
||||
|
||||
static vector<string> module_list;
|
||||
|
||||
class node_entry;
|
||||
class dir_node;
|
||||
class inter_node;
|
||||
@@ -543,12 +541,22 @@ static void inject_magisk_bins(root_node *system) {
|
||||
delete bin->extract(init_applet[i]);
|
||||
}
|
||||
|
||||
struct module_info {
|
||||
string name;
|
||||
int z32 = -1;
|
||||
#if defined(__LP64__)
|
||||
int z64 = -1;
|
||||
#endif
|
||||
};
|
||||
|
||||
static vector<module_info> *modules;
|
||||
|
||||
#define mount_zygisk(bit) \
|
||||
if (access("/system/bin/app_process" #bit, F_OK) == 0) { \
|
||||
string zbin = zygisk_bin + "/app_process" #bit; \
|
||||
string mbin = MAGISKTMP + "/magisk" #bit; \
|
||||
int src = xopen(mbin.data(), O_RDONLY); \
|
||||
int out = xopen(zbin.data(), O_CREAT | O_WRONLY, 0); \
|
||||
int src = xopen(mbin.data(), O_RDONLY | O_CLOEXEC); \
|
||||
int out = xopen(zbin.data(), O_CREAT | O_WRONLY | O_CLOEXEC, 0); \
|
||||
xsendfile(out, src, nullptr, INT_MAX); \
|
||||
close(src); \
|
||||
close(out); \
|
||||
@@ -566,8 +574,8 @@ void magic_mount() {
|
||||
|
||||
char buf[4096];
|
||||
LOGI("* Loading modules\n");
|
||||
for (const auto &m : module_list) {
|
||||
auto module = m.data();
|
||||
for (const auto &m : *modules) {
|
||||
const char *module = m.name.data();
|
||||
char *b = buf + sprintf(buf, "%s/" MODULEMNT "/%s/", MAGISKTMP.data(), module);
|
||||
|
||||
// Read props
|
||||
@@ -676,8 +684,8 @@ static void foreach_module(Func fn) {
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_modules() {
|
||||
foreach_module([](int dfd, dirent *entry, int modfd) {
|
||||
static void collect_modules(bool open_zygisk) {
|
||||
foreach_module([=](int dfd, dirent *entry, int modfd) {
|
||||
if (faccessat(modfd, "remove", F_OK, 0) == 0) {
|
||||
LOGI("%s: remove\n", entry->d_name);
|
||||
auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh";
|
||||
@@ -690,24 +698,42 @@ static void collect_modules() {
|
||||
unlinkat(modfd, "update", 0);
|
||||
if (faccessat(modfd, "disable", F_OK, 0) == 0)
|
||||
return;
|
||||
// Riru and its modules are not compatible with zygisk
|
||||
if (zygisk_enabled && (
|
||||
entry->d_name == "riru-core"sv ||
|
||||
faccessat(modfd, "riru", F_OK, 0) == 0))
|
||||
return;
|
||||
|
||||
module_list.emplace_back(entry->d_name);
|
||||
module_info info;
|
||||
if (zygisk_enabled) {
|
||||
// Riru and its modules are not compatible with zygisk
|
||||
if (entry->d_name == "riru-core"sv || faccessat(modfd, "riru", F_OK, 0) == 0)
|
||||
return;
|
||||
if (open_zygisk) {
|
||||
#if defined(__arm__)
|
||||
info.z32 = openat(modfd, "zygisk/armeabi-v7a.so", O_RDONLY | O_CLOEXEC);
|
||||
#elif defined(__aarch64__)
|
||||
info.z32 = openat(modfd, "zygisk/armeabi-v7a.so", O_RDONLY | O_CLOEXEC);
|
||||
info.z64 = openat(modfd, "zygisk/arm64-v8a.so", O_RDONLY | O_CLOEXEC);
|
||||
#elif defined(__i386__)
|
||||
info.z32 = openat(modfd, "zygisk/x86.so", O_RDONLY | O_CLOEXEC);
|
||||
#elif defined(__x86_64__)
|
||||
info.z32 = openat(modfd, "zygisk/x86.so", O_RDONLY | O_CLOEXEC);
|
||||
info.z64 = openat(modfd, "zygisk/x86_64.so", O_RDONLY | O_CLOEXEC);
|
||||
#else
|
||||
#error Unsupported ABI
|
||||
#endif
|
||||
}
|
||||
}
|
||||
info.name = entry->d_name;
|
||||
modules->push_back(info);
|
||||
});
|
||||
}
|
||||
|
||||
void handle_modules() {
|
||||
default_new(modules);
|
||||
prepare_modules();
|
||||
collect_modules();
|
||||
collect_modules(false);
|
||||
exec_module_scripts("post-fs-data");
|
||||
|
||||
// Recollect modules (module scripts could remove itself)
|
||||
module_list.clear();
|
||||
collect_modules();
|
||||
modules->clear();
|
||||
collect_modules(true);
|
||||
}
|
||||
|
||||
void disable_modules() {
|
||||
@@ -726,5 +752,25 @@ void remove_modules() {
|
||||
}
|
||||
|
||||
void exec_module_scripts(const char *stage) {
|
||||
exec_module_scripts(stage, module_list);
|
||||
vector<string_view> module_names;
|
||||
std::transform(modules->begin(), modules->end(), std::back_inserter(module_names),
|
||||
[](const module_info &info) { return info.name; });
|
||||
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;
|
||||
}
|
||||
|
@@ -107,16 +107,15 @@ void exec_common_scripts(const char *stage) {
|
||||
PFS_DONE()
|
||||
}
|
||||
|
||||
// Return if a > b
|
||||
static bool timespec_larger(timespec *a, timespec *b) {
|
||||
if (a->tv_sec != b->tv_sec)
|
||||
return a->tv_sec > b->tv_sec;
|
||||
return a->tv_nsec > b->tv_nsec;
|
||||
static bool operator>(const timespec &a, const timespec &b) {
|
||||
if (a.tv_sec != b.tv_sec)
|
||||
return a.tv_sec > b.tv_sec;
|
||||
return a.tv_nsec > b.tv_nsec;
|
||||
}
|
||||
|
||||
void exec_module_scripts(const char *stage, const vector<string> &module_list) {
|
||||
void exec_module_scripts(const char *stage, const vector<string_view> &modules) {
|
||||
LOGI("* Running module %s scripts\n", stage);
|
||||
if (module_list.empty())
|
||||
if (modules.empty())
|
||||
return;
|
||||
|
||||
bool pfs = stage == "post-fs-data"sv;
|
||||
@@ -124,15 +123,15 @@ void exec_module_scripts(const char *stage, const vector<string> &module_list) {
|
||||
timespec now{};
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
// If we had already timed out, treat it as service mode
|
||||
if (timespec_larger(&now, &pfs_timeout))
|
||||
if (now > pfs_timeout)
|
||||
pfs = false;
|
||||
}
|
||||
int timer_pid = -1;
|
||||
PFS_SETUP()
|
||||
|
||||
char path[4096];
|
||||
for (auto &m : module_list) {
|
||||
const char* module = m.data();
|
||||
for (auto &m : modules) {
|
||||
const char *module = m.data();
|
||||
sprintf(path, MODULEROOT "/%s/%s.sh", module, stage);
|
||||
if (access(path, F_OK) == -1)
|
||||
continue;
|
||||
|
@@ -93,14 +93,17 @@ static void *recv_fds(int sockfd, char *cmsgbuf, size_t bufsz, int cnt) {
|
||||
}
|
||||
|
||||
vector<int> recv_fds(int sockfd) {
|
||||
vector<int> results;
|
||||
|
||||
// Peek fd count to allocate proper buffer
|
||||
int cnt;
|
||||
recv(sockfd, &cnt, sizeof(cnt), MSG_PEEK);
|
||||
if (cnt == 0)
|
||||
return results;
|
||||
|
||||
vector<char> cmsgbuf;
|
||||
cmsgbuf.resize(CMSG_SPACE(sizeof(int) * cnt));
|
||||
|
||||
vector<int> results;
|
||||
void *data = recv_fds(sockfd, cmsgbuf.data(), cmsgbuf.size(), cnt);
|
||||
if (data == nullptr)
|
||||
return results;
|
||||
|
Reference in New Issue
Block a user