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
************************/
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<tmpfs_node>(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,23 +163,24 @@ 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<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);
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();
}
}
/****************
* Magisk Stuffs
@ -191,7 +195,7 @@ public:
if (access(src.data(), F_OK))
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") {
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:

View File

@ -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<bool>(_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();
}