Load Zygisk modules

This commit is contained in:
topjohnwu
2021-10-13 04:52:02 -07:00
parent 27814e3015
commit c8ac6c07b0
10 changed files with 366 additions and 120 deletions

View File

@@ -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);

View 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;
}

View File

@@ -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;

View File

@@ -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;