Keep mirror shared before magic mount

This allows mounting during post-fs-data be kept after magic mount
This commit is contained in:
LoveSy 2023-12-22 13:29:56 +08:00 committed by John Wu
parent 06687abffc
commit 27ece3c7df

View File

@ -20,13 +20,11 @@ bool zygisk_enabled = false;
* Setup * * Setup *
*********/ *********/
static bool mount_mirror(const std::string_view from, const std::string_view to) { static bool rec_mount(const std::string_view from, const std::string_view to) {
return !xmkdirs(to.data(), 0755) && return !xmkdirs(to.data(), 0755) &&
// recursively bind mount to mirror dir, rootfs will fail before 3.12 kernel // recursively bind mount to mirror dir, rootfs will fail before 3.12 kernel
// because of MS_NOUSER // because of MS_NOUSER
!mount(from.data(), to.data(), nullptr, MS_BIND | MS_REC, nullptr) && !mount(from.data(), to.data(), nullptr, MS_BIND | MS_REC, nullptr);
// make mirror dir as a private mount so that it won't be affected by magic mount
!xmount(nullptr, to.data(), nullptr, MS_PRIVATE | MS_REC, nullptr);
} }
static void mount_mirrors() { static void mount_mirrors() {
@ -67,7 +65,7 @@ static void mount_mirrors() {
if (!rw) continue; if (!rw) continue;
string preinit_dir = resolve_preinit_dir(info.target.data()); string preinit_dir = resolve_preinit_dir(info.target.data());
xmkdir(preinit_dir.data(), 0700); xmkdir(preinit_dir.data(), 0700);
if ((mounted = mount_mirror(preinit_dir, path))) { if ((mounted = rec_mount(preinit_dir, path))) {
xmount(nullptr, path, nullptr, MS_UNBINDABLE, nullptr); xmount(nullptr, path, nullptr, MS_UNBINDABLE, nullptr);
break; break;
} }
@ -83,10 +81,12 @@ static void mount_mirrors() {
ssprintf(path, sizeof(path), "%s/" WORKERDIR, get_magisk_tmp()); ssprintf(path, sizeof(path), "%s/" WORKERDIR, get_magisk_tmp());
xmount("worker", path, "tmpfs", 0, "mode=755"); xmount("worker", path, "tmpfs", 0, "mode=755");
xmount(nullptr, path, nullptr, MS_PRIVATE, nullptr); xmount(nullptr, path, nullptr, MS_PRIVATE, nullptr);
// Recursively bind mount / to mirror dir // Recursively bind mount / to mirror dir
if (auto mirror_dir = get_magisk_tmp() + "/"s MIRRDIR; !mount_mirror("/", mirror_dir)) { // Keep mirror shared so that mounting during post-fs-data will be propagated
if (auto mirror_dir = get_magisk_tmp() + "/"s MIRRDIR; !rec_mount("/", mirror_dir)) {
LOGI("fallback to mount subtree\n"); LOGI("fallback to mount subtree\n");
// create new a bind mount for easy make private
xmount(mirror_dir.data(), mirror_dir.data(), nullptr, MS_BIND, nullptr);
// rootfs may fail, fallback to bind mount each mount point // rootfs may fail, fallback to bind mount each mount point
set<string, greater<>> mounted_dirs {{ get_magisk_tmp() }}; set<string, greater<>> mounted_dirs {{ get_magisk_tmp() }};
for (const auto &info: self_mount_info) { for (const auto &info: self_mount_info) {
@ -96,7 +96,7 @@ static void mount_mirrors() {
last_mount != mounted_dirs.end() && info.target.starts_with(*last_mount + '/')) { last_mount != mounted_dirs.end() && info.target.starts_with(*last_mount + '/')) {
continue; continue;
} }
if (mount_mirror(info.target, mirror_dir + info.target)) { if (rec_mount(info.target, mirror_dir + info.target)) {
LOGD("%-8s: %s <- %s\n", "rbind", (mirror_dir + info.target).data(), info.target.data()); LOGD("%-8s: %s <- %s\n", "rbind", (mirror_dir + info.target).data(), info.target.data());
mounted_dirs.insert(info.target); mounted_dirs.insert(info.target);
} }
@ -342,6 +342,9 @@ bool MagiskD::post_fs_data() const {
early_abort: early_abort:
auto mirror_dir = get_magisk_tmp() + "/"s MIRRDIR; auto mirror_dir = get_magisk_tmp() + "/"s MIRRDIR;
// make mirror dir as a private mount so that it won't be affected by magic mount
LOGD("make %s private\n", mirror_dir.data());
xmount(nullptr, mirror_dir.data(), nullptr, MS_PRIVATE | MS_REC, nullptr);
// We still do magic mount because root itself might need it // We still do magic mount because root itself might need it
load_modules(); load_modules();
// make mirror dir as a shared mount to make magisk --stop work for other ns // make mirror dir as a shared mount to make magisk --stop work for other ns