From 1fd49e498780c2843749c9ea240489bea2f85738 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Mon, 4 Dec 2023 21:11:42 +0800 Subject: [PATCH] Make tmpfs mount of magic mount atomic This avoid system libraries disappear temporarily during magic mount, which causes some dynamic executables fails to run during post-fs-data. --- native/src/core/module.cpp | 36 +++++++++++++++++++----------------- native/src/core/node.hpp | 8 +++++++- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/native/src/core/module.cpp b/native/src/core/module.cpp index 467f146d6..59310ab01 100644 --- a/native/src/core/module.cpp +++ b/native/src/core/module.cpp @@ -122,8 +122,8 @@ void dir_node::collect_module_files(const char *module, int dfd) { * Mount Implementations ************************/ -void node_entry::create_and_mount(const char *reason, const string &src) { - const string &dest = node_path(); +void node_entry::create_and_mount(const char *reason, const string &src, bool ro) { + const string dest = isa(parent()) ? worker_path() : node_path(); if (is_lnk()) { VLOGD("cp_link", src.data(), dest.data()); cp_afc(src.data(), dest.data()); @@ -135,6 +135,9 @@ void node_entry::create_and_mount(const char *reason, const string &src) { else return; bind_mount(reason, src.data(), dest.data()); + if (ro) { + xmount(nullptr, dest.data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr); + } } } @@ -160,22 +163,23 @@ void module_node::mount() { void tmpfs_node::mount() { string src = mirror_path(); - const string &dest = node_path(); - const char *src_path; - if (access(src.data(), F_OK) == 0) - src_path = src.data(); - else - src_path = parent()->node_path().data(); + const char *src_path = access(src.data(), F_OK) == 0 ? src.data() : parent()->node_path().data(); if (!isa(parent())) { - auto worker_dir = get_magisk_tmp() + "/"s WORKERDIR + dest; + const string &dest = node_path(); + auto worker_dir = worker_path(); mkdirs(worker_dir.data(), 0); - create_and_mount(skip_mirror() ? "replace" : "tmpfs", worker_dir); + bind_mount("tmpfs", worker_dir.data(), worker_dir.data()); + dir_node::mount(); + VLOGD(skip_mirror() ? "replace" : "move", worker_dir.data(), dest.data()); + xmount(worker_dir.data(), dest.data(), nullptr, MS_MOVE, nullptr); + clone_attr(src_path, dest.data()); } else { + const string dest = worker_path(); // We don't need another layer of tmpfs if parent is tmpfs mkdir(dest.data(), 0); + clone_attr(src_path, dest.data()); + dir_node::mount(); } - clone_attr(src_path, dest.data()); - dir_node::mount(); } /**************** @@ -191,7 +195,7 @@ public: if (access(src.data(), F_OK)) return; - const string &dir_name = parent()->node_path(); + const string dir_name = isa(parent()) ? parent()->worker_path() : parent()->node_path(); if (name() == "magisk") { for (int i = 0; applet_names[i]; ++i) { string dest = dir_name + "/" + applet_names[i]; @@ -203,8 +207,7 @@ public: VLOGD("create", "./magiskpolicy", dest.data()); xsymlink("./magiskpolicy", dest.data()); } - create_and_mount("magisk", src); - xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr); + create_and_mount("magisk", src, true); } }; @@ -215,8 +218,7 @@ public: void mount() override { const string src = get_magisk_tmp() + "/magisk"s + (is64bit ? "64" : "32"); - create_and_mount("zygisk", src); - xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr); + create_and_mount("zygisk", src, true); } private: diff --git a/native/src/core/node.hpp b/native/src/core/node.hpp index a75d290ed..f0969cc49 100644 --- a/native/src/core/node.hpp +++ b/native/src/core/node.hpp @@ -45,6 +45,8 @@ public: // Don't call the following two functions before prepare const string &node_path(); + const string worker_path(); + string mirror_path() { return mirror_dir + node_path(); } virtual void mount() = 0; @@ -67,7 +69,7 @@ protected: delete other; } - void create_and_mount(const char *reason, const string &src); + void create_and_mount(const char *reason, const string &src, bool ro=false); // Use bit 7 of _file_type for exist status bool exist() const { return static_cast(_file_type & (1 << 7)); } @@ -314,3 +316,7 @@ const string &node_entry::node_path() { _node_path = _parent->node_path() + '/' + _name; return _node_path; } + +const string node_entry::worker_path() { + return get_magisk_tmp() + "/"s WORKERDIR + node_path(); +}