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.
This commit is contained in:
LoveSy 2023-12-04 21:11:42 +08:00 committed by John Wu
parent d49b02b274
commit 1fd49e4987
2 changed files with 26 additions and 18 deletions

View File

@ -122,8 +122,8 @@ void dir_node::collect_module_files(const char *module, int dfd) {
* Mount Implementations * Mount Implementations
************************/ ************************/
void node_entry::create_and_mount(const char *reason, const string &src) { void node_entry::create_and_mount(const char *reason, const string &src, bool ro) {
const string &dest = node_path(); const string dest = isa<tmpfs_node>(parent()) ? worker_path() : node_path();
if (is_lnk()) { if (is_lnk()) {
VLOGD("cp_link", src.data(), dest.data()); VLOGD("cp_link", src.data(), dest.data());
cp_afc(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 else
return; return;
bind_mount(reason, src.data(), dest.data()); 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() { void tmpfs_node::mount() {
string src = mirror_path(); string src = mirror_path();
const string &dest = node_path(); const char *src_path = access(src.data(), F_OK) == 0 ? src.data() : parent()->node_path().data();
const char *src_path;
if (access(src.data(), F_OK) == 0)
src_path = src.data();
else
src_path = parent()->node_path().data();
if (!isa<tmpfs_node>(parent())) { if (!isa<tmpfs_node>(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); 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 { } else {
const string dest = worker_path();
// We don't need another layer of tmpfs if parent is tmpfs // We don't need another layer of tmpfs if parent is tmpfs
mkdir(dest.data(), 0); mkdir(dest.data(), 0);
}
clone_attr(src_path, dest.data()); clone_attr(src_path, dest.data());
dir_node::mount(); dir_node::mount();
}
} }
/**************** /****************
@ -191,7 +195,7 @@ public:
if (access(src.data(), F_OK)) if (access(src.data(), F_OK))
return; return;
const string &dir_name = parent()->node_path(); const string dir_name = isa<tmpfs_node>(parent()) ? parent()->worker_path() : parent()->node_path();
if (name() == "magisk") { if (name() == "magisk") {
for (int i = 0; applet_names[i]; ++i) { for (int i = 0; applet_names[i]; ++i) {
string dest = dir_name + "/" + applet_names[i]; string dest = dir_name + "/" + applet_names[i];
@ -203,8 +207,7 @@ public:
VLOGD("create", "./magiskpolicy", dest.data()); VLOGD("create", "./magiskpolicy", dest.data());
xsymlink("./magiskpolicy", dest.data()); xsymlink("./magiskpolicy", dest.data());
} }
create_and_mount("magisk", src); create_and_mount("magisk", src, true);
xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr);
} }
}; };
@ -215,8 +218,7 @@ public:
void mount() override { void mount() override {
const string src = get_magisk_tmp() + "/magisk"s + (is64bit ? "64" : "32"); const string src = get_magisk_tmp() + "/magisk"s + (is64bit ? "64" : "32");
create_and_mount("zygisk", src); create_and_mount("zygisk", src, true);
xmount(nullptr, node_path().data(), nullptr, MS_REMOUNT | MS_BIND | MS_RDONLY, nullptr);
} }
private: private:

View File

@ -45,6 +45,8 @@ public:
// Don't call the following two functions before prepare // Don't call the following two functions before prepare
const string &node_path(); const string &node_path();
const string worker_path();
string mirror_path() { return mirror_dir + node_path(); } string mirror_path() { return mirror_dir + node_path(); }
virtual void mount() = 0; virtual void mount() = 0;
@ -67,7 +69,7 @@ protected:
delete other; 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 // Use bit 7 of _file_type for exist status
bool exist() const { return static_cast<bool>(_file_type & (1 << 7)); } bool exist() const { return static_cast<bool>(_file_type & (1 << 7)); }
@ -314,3 +316,7 @@ const string &node_entry::node_path() {
_node_path = _parent->node_path() + '/' + _name; _node_path = _parent->node_path() + '/' + _name;
return _node_path; return _node_path;
} }
const string node_entry::worker_path() {
return get_magisk_tmp() + "/"s WORKERDIR + node_path();
}