diff --git a/native/src/core/bootstages.cpp b/native/src/core/bootstages.cpp index 439bff757..5dfd97ec6 100644 --- a/native/src/core/bootstages.cpp +++ b/native/src/core/bootstages.cpp @@ -179,7 +179,6 @@ bool MagiskD::post_fs_data() const noexcept { initialize_denylist(); setup_mounts(); handle_modules(); - load_modules(); return false; } @@ -189,7 +188,7 @@ void MagiskD::late_start() const noexcept { LOGI("** late_start service mode running\n"); exec_common_scripts("service"); - exec_module_scripts("service"); + exec_module_scripts("service", module_list()); } void MagiskD::boot_complete() const noexcept { diff --git a/native/src/core/daemon.cpp b/native/src/core/daemon.cpp index b2a6ad50d..f66f598a3 100644 --- a/native/src/core/daemon.cpp +++ b/native/src/core/daemon.cpp @@ -378,7 +378,6 @@ static void daemon_entry() { default_new(poll_map); default_new(poll_fds); - default_new(module_list); // Register handler for main socket pollfd main_socket_pfd = { fd, POLLIN, 0 }; diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index b6d95c2b6..343536df7 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -1,6 +1,6 @@ use crate::consts::{MAGISK_FULL_VER, MAIN_CONFIG}; use crate::db::Sqlite3; -use crate::ffi::{get_magisk_tmp, RequestCode}; +use crate::ffi::{get_magisk_tmp, ModuleInfo, RequestCode}; use crate::get_prop; use crate::logging::{magisk_logging, start_log_daemon}; use crate::package::ManagerInfo; @@ -59,6 +59,7 @@ pub struct MagiskD { pub sql_connection: Mutex>, pub manager_info: Mutex, boot_stage_lock: Mutex, + module_list: OnceLock>, sdk_int: i32, pub is_emulator: bool, is_recovery: bool, @@ -73,6 +74,14 @@ impl MagiskD { self.sdk_int } + pub fn set_module_list(&self, module_list: Vec) { + self.module_list.set(module_list).ok(); + } + + pub fn module_list(&self) -> &Vec { + self.module_list.get().unwrap() + } + pub fn app_data_dir(&self) -> &'static Utf8CStr { if self.sdk_int >= 24 { cstr!("/data/user_de") diff --git a/native/src/core/include/core.hpp b/native/src/core/include/core.hpp index 81f08ec1e..8554a7eae 100644 --- a/native/src/core/include/core.hpp +++ b/native/src/core/include/core.hpp @@ -26,16 +26,7 @@ enum class RespondCode : int { END }; -struct module_info { - std::string name; - int z32 = -1; -#if defined(__LP64__) - int z64 = -1; -#endif -}; - extern bool zygisk_enabled; -extern std::vector *module_list; extern std::string native_bridge; void reset_zygisk(bool restore); @@ -58,16 +49,13 @@ void su_daemon_handler(int client, const sock_cred *cred); void zygisk_handler(int client, const sock_cred *cred); // Module stuffs -void handle_modules(); -void load_modules(); void disable_modules(); void remove_modules(); -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 &modules); +void exec_module_scripts(const char *stage, const rust::Vec &module_list); void clear_pkg(const char *pkg, int user_id); [[noreturn]] void install_module(const char *file); diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index 589752e96..de4b74984 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -135,6 +135,12 @@ pub mod ffi { notify: bool, } + struct ModuleInfo { + name: String, + z32: i32, + z64: i32, + } + unsafe extern "C++" { include!("include/sqlite.hpp"); @@ -185,6 +191,8 @@ pub mod ffi { fn uid_granted_root(&self, mut uid: i32) -> bool; #[cxx_name = "get_manager"] unsafe fn get_manager_for_cxx(&self, user: i32, ptr: *mut CxxString, install: bool) -> i32; + fn set_module_list(&self, module_list: Vec); + fn module_list(&self) -> &Vec; #[cxx_name = "get_db_settings"] fn get_db_settings_for_cxx(&self, cfg: &mut DbSettings) -> bool; @@ -209,6 +217,8 @@ pub mod ffi { fn post_fs_data(self: &MagiskD) -> bool; fn late_start(self: &MagiskD); fn boot_complete(self: &MagiskD); + #[allow(dead_code)] + fn handle_modules(self: &MagiskD); } } diff --git a/native/src/core/module.cpp b/native/src/core/module.cpp index 34f886aaf..d246abf17 100644 --- a/native/src/core/module.cpp +++ b/native/src/core/module.cpp @@ -86,7 +86,7 @@ bool dir_node::prepare() { return upgrade_to_tmpfs; } -void dir_node::collect_module_files(const char *module, int dfd) { +void dir_node::collect_module_files(std::string_view module, int dfd) { auto dir = xopen_dir(xopenat(dfd, name().data(), O_RDONLY | O_CLOEXEC)); if (!dir) return; @@ -149,7 +149,9 @@ void module_node::mount() { VLOGD("delete", "null", node_path().data()); return; } - std::string path = module + (parent()->root()->prefix + node_path()); + std::string path{module.begin(), module.end()}; + path += parent()->root()->prefix; + path += node_path(); string mnt_src = module_mnt + path; { string src = MODULEROOT "/" + path; @@ -267,9 +269,7 @@ static void inject_zygisk_libs(root_node *system) { } } -vector *module_list; - -void load_modules() { +static void load_modules(const rust::Vec &module_list) { node_entry::module_mnt = get_magisk_tmp() + "/"s MODULEMNT "/"; auto root = make_unique(""); @@ -278,14 +278,14 @@ void load_modules() { char buf[4096]; LOGI("* Loading modules\n"); - for (const auto &m : *module_list) { - const char *module = m.name.data(); - char *b = buf + ssprintf(buf, sizeof(buf), "%s/" MODULEMNT "/%s/", get_magisk_tmp(), module); + for (const auto &m : module_list) { + char *b = buf + ssprintf(buf, sizeof(buf), "%s/" MODULEMNT "/%.*s/", + get_magisk_tmp(), (int) m.name.size(), m.name.data()); // Read props strcpy(b, "system.prop"); if (access(buf, F_OK) == 0) { - LOGI("%s: loading [system.prop]\n", module); + LOGI("%.*s: loading [system.prop]\n", (int) m.name.size(), m.name.data()); // Do NOT go through property service as it could cause boot lock load_prop_file(buf, true); } @@ -300,10 +300,10 @@ void load_modules() { if (access(buf, F_OK) != 0) continue; - LOGI("%s: loading mount files\n", module); + LOGI("%.*s: loading mount files\n", (int) m.name.size(), m.name.data()); b[-1] = '\0'; int fd = xopen(buf, O_RDONLY | O_CLOEXEC); - system->collect_module_files(module, fd); + system->collect_module_files({ m.name.begin(), m.name.end() }, fd); close(fd); } if (get_magisk_tmp() != "/sbin"sv || !str_contains(getenv("PATH") ?: "", "/sbin")) { @@ -392,8 +392,9 @@ static void foreach_module(Func fn) { } } -static void collect_modules(bool open_zygisk) { - foreach_module([=](int dfd, dirent *entry, int modfd) { +static rust::Vec collect_modules(bool open_zygisk) { + rust::Vec modules; + 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"; @@ -407,7 +408,7 @@ static void collect_modules(bool open_zygisk) { if (faccessat(modfd, "disable", F_OK, 0) == 0) return; - module_info info; + ModuleInfo 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) { @@ -417,11 +418,13 @@ static void collect_modules(bool open_zygisk) { if (open_zygisk) { #if defined(__arm__) info.z32 = openat(modfd, "zygisk/armeabi-v7a.so", O_RDONLY | O_CLOEXEC); + info.z64 = -1; #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); + info.z64 = -1; #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); @@ -441,7 +444,7 @@ static void collect_modules(bool open_zygisk) { } } info.name = entry->d_name; - module_list->push_back(info); + modules.push_back(std::move(info)); }); if (zygisk_enabled) { bool use_memfd = true; @@ -461,23 +464,23 @@ static void collect_modules(bool open_zygisk) { } return fd; }; - std::for_each(module_list->begin(), module_list->end(), [&](module_info &info) { + std::for_each(modules.begin(),modules.end(), [&](ModuleInfo &info) { info.z32 = convert_to_memfd(info.z32); #if defined(__LP64__) info.z64 = convert_to_memfd(info.z64); #endif }); } + return modules; } -void handle_modules() { +void MagiskD::handle_modules() const noexcept { prepare_modules(); - collect_modules(false); - exec_module_scripts("post-fs-data"); - + exec_module_scripts("post-fs-data", collect_modules(false)); // Recollect modules (module scripts could remove itself) - module_list->clear(); - collect_modules(true); + auto list = collect_modules(true); + load_modules(list); + set_module_list(std::move(list)); } static int check_rules_dir(char *buf, size_t sz) { @@ -517,10 +520,3 @@ void remove_modules() { }); rm_rf(MODULEROOT); } - -void exec_module_scripts(const char *stage) { - vector module_names; - std::transform(module_list->begin(), module_list->end(), std::back_inserter(module_names), - [](const module_info &info) -> string_view { return info.name; }); - exec_module_scripts(stage, module_names); -} diff --git a/native/src/core/node.hpp b/native/src/core/node.hpp index 5324ef38f..744df261c 100644 --- a/native/src/core/node.hpp +++ b/native/src/core/node.hpp @@ -105,7 +105,7 @@ public: **************/ // Traverse through module directories to generate a tree of module files - void collect_module_files(const char *module, int dfd); + void collect_module_files(std::string_view module, int dfd); // Traverse through the real filesystem and prepare the tree for magic mount. // Return true to indicate that this node needs to be upgraded to tmpfs_node. @@ -279,16 +279,16 @@ public: class module_node : public node_entry { public: - module_node(const char *module, dirent *entry) + module_node(std::string_view module, dirent *entry) : node_entry(entry->d_name, entry->d_type, this), module(module) {} - module_node(node_entry *node, const char *module) : node_entry(this), module(module) { + module_node(node_entry *node, std::string_view module) : node_entry(this), module(module) { node_entry::consume(node); } void mount() override; private: - const char *module; + std::string_view module; }; // Don't create tmpfs_node before prepare diff --git a/native/src/core/scripting.cpp b/native/src/core/scripting.cpp index d2ffd8ce9..b24a84db4 100644 --- a/native/src/core/scripting.cpp +++ b/native/src/core/scripting.cpp @@ -117,9 +117,9 @@ static bool operator>(const timespec &a, const timespec &b) { return a.tv_nsec > b.tv_nsec; } -void exec_module_scripts(const char *stage, const vector &modules) { +void exec_module_scripts(const char *stage, const rust::Vec &module_list) { LOGI("* Running module %s scripts\n", stage); - if (modules.empty()) + if (module_list.empty()) return; bool pfs = stage == "post-fs-data"sv; @@ -134,12 +134,11 @@ void exec_module_scripts(const char *stage, const vector &modules) PFS_SETUP() char path[4096]; - for (auto &m : modules) { - const char *module = m.data(); - sprintf(path, MODULEROOT "/%s/%s.sh", module, stage); + for (auto &m : module_list) { + sprintf(path, MODULEROOT "/%.*s/%s.sh", (int) m.name.size(), m.name.data(), stage); if (access(path, F_OK) == -1) continue; - LOGI("%s: exec [%s.sh]\n", module, stage); + LOGI("%.*s: exec [%s.sh]\n", (int) m.name.size(), m.name.data(), stage); exec_t exec { .pre_exec = set_script_env, .fork = pfs ? xfork : fork_dont_care diff --git a/native/src/core/zygisk/entry.cpp b/native/src/core/zygisk/entry.cpp index 69ba7528a..fbad3069e 100644 --- a/native/src/core/zygisk/entry.cpp +++ b/native/src/core/zygisk/entry.cpp @@ -15,6 +15,8 @@ using namespace std; string native_bridge = "0"; +using modules_t = const rust::Vec&; + static bool is_compatible_with(uint32_t) { zygisk_logging(); hook_entry(); @@ -55,20 +57,20 @@ int remote_get_info(int uid, const char *process, uint32_t *flags, vector & // The following code runs in magiskd -static vector get_module_fds(bool is_64_bit) { +static vector get_module_fds(bool is_64_bit, modules_t module_list) { vector 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 defined(__LP64__) if (is_64_bit) { - std::transform(module_list->begin(), module_list->end(), std::back_inserter(fds), - [](const module_info &info) { return info.z64 < 0 ? STDOUT_FILENO : info.z64; }); + std::transform(module_list.begin(), module_list.end(), std::back_inserter(fds), + [](const ModuleInfo &info) { return info.z64 < 0 ? STDOUT_FILENO : info.z64; }); } else #endif { - std::transform(module_list->begin(), module_list->end(), std::back_inserter(fds), - [](const module_info &info) { return info.z32 < 0 ? STDOUT_FILENO : info.z32; }); + std::transform(module_list.begin(), module_list.end(), std::back_inserter(fds), + [](const ModuleInfo &info) { return info.z32 < 0 ? STDOUT_FILENO : info.z32; }); } return fds; } @@ -77,9 +79,10 @@ static pthread_mutex_t zygiskd_lock = PTHREAD_MUTEX_INITIALIZER; static int zygiskd_sockets[] = { -1, -1 }; #define zygiskd_socket zygiskd_sockets[is_64_bit] -static void connect_companion(int client, bool is_64_bit) { +static void connect_companion(int client, modules_t module_list) { mutex_guard g(zygiskd_lock); + bool is_64_bit = read_int(client); if (zygiskd_socket >= 0) { // Make sure the socket is still valid pollfd pfd = { zygiskd_socket, 0, 0 }; @@ -109,7 +112,7 @@ static void connect_companion(int client, bool is_64_bit) { exit(-1); } close(fds[1]); - vector module_fds = get_module_fds(is_64_bit); + vector module_fds = get_module_fds(is_64_bit, module_list); send_fds(zygiskd_socket, module_fds.data(), module_fds.size()); // Wait for ack if (read_int(zygiskd_socket) != 0) { @@ -120,7 +123,7 @@ static void connect_companion(int client, bool is_64_bit) { send_fd(zygiskd_socket, client); } -static void get_process_info(int client, const sock_cred *cred) { +static void get_process_info(int client, const sock_cred *cred, modules_t module_list) { int uid = read_int(client); string process = read_string(client); int arch = read_int(client); @@ -144,7 +147,7 @@ static void get_process_info(int client, const sock_cred *cred) { xwrite(client, &flags, sizeof(flags)); if (should_load_modules(flags)) { - vector fds = get_module_fds(arch); + vector fds = get_module_fds(arch, module_list); send_fds(client, fds.data(), fds.size()); } @@ -159,12 +162,12 @@ static void get_process_info(int client, const sock_cred *cred) { xxread(client, &l, sizeof(l)); bits.emplace_back(l); } - for (int id = 0; id < module_list->size(); ++id) { + for (int id = 0; id < module_list.size(); ++id) { if (!as_const(bits)[id]) { // Either not a zygisk module, or incompatible char buf[4096]; ssprintf(buf, sizeof(buf), MODULEROOT "/%s/zygisk", - module_list->operator[](id).name.data()); + module_list[id].name.data()); if (int dirfd = open(buf, O_RDONLY | O_CLOEXEC); dirfd >= 0) { close(xopenat(dirfd, "unloaded", O_CREAT | O_RDONLY, 0644)); close(dirfd); @@ -173,28 +176,28 @@ static void get_process_info(int client, const sock_cred *cred) { } } -static void get_moddir(int client) { +static void get_moddir(int client, modules_t module_list) { int id = read_int(client); char buf[4096]; - ssprintf(buf, sizeof(buf), MODULEROOT "/%s", module_list->operator[](id).name.data()); + auto &m = module_list[id]; + ssprintf(buf, sizeof(buf), MODULEROOT "/%.*s", (int) m.name.size(), m.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) { + auto &module_list = MagiskD().module_list(); int code = read_int(client); switch (code) { case ZygiskRequest::GET_INFO: - get_process_info(client, cred); + get_process_info(client, cred, module_list); break; - case ZygiskRequest::CONNECT_COMPANION: { - int arch = read_int(client); - connect_companion(client, arch); + case ZygiskRequest::CONNECT_COMPANION: + connect_companion(client, module_list); break; - } case ZygiskRequest::GET_MODDIR: - get_moddir(client); + get_moddir(client, module_list); break; default: // Unknown code