From bdbfb403833135f487030d7b0034f06c14eb4df1 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Fri, 14 Nov 2025 23:32:00 +0800 Subject: [PATCH] Use rootfs for magisktmp if possible --- native/src/base/mount.rs | 44 +++++++++++++++++++++++++++++++++++- native/src/core/mount.rs | 3 ++- native/src/init/init.rs | 26 +++++++++++++++++---- native/src/init/mount.rs | 43 ++++++++++++++++++++++++----------- native/src/init/twostage.rs | 18 ++++----------- native/src/sepolicy/rules.rs | 2 +- 6 files changed, 103 insertions(+), 33 deletions(-) diff --git a/native/src/base/mount.rs b/native/src/base/mount.rs index 4c0dc7818..f71fcf5f7 100644 --- a/native/src/base/mount.rs +++ b/native/src/base/mount.rs @@ -1,4 +1,4 @@ -use crate::{LibcReturn, OsResult, Utf8CStr}; +use crate::{Directory, LibcReturn, OsResult, ResultExt, Utf8CStr, Utf8CStrBufArr, WalkResult::{Continue, Skip}}; use nix::mount::{MntFlags, MsFlags, mount, umount2}; impl Utf8CStr { @@ -81,4 +81,46 @@ impl Utf8CStr { ) .check_os_err("set_mount_private", Some(self), None) } + + pub fn occupy(&self) { + Directory::open(self).and_then(|mut dir| { + dir.pre_order_walk(|entry| { + let mut path = Utf8CStrBufArr::default(); + entry.resolve_path(&mut path)?; + let path = path.as_utf8_cstr(); + mount( + Some(path), + path, + None::<&Utf8CStr>, + MsFlags::MS_BIND | MsFlags::MS_RDONLY, + None::<&Utf8CStr>, + ).check_os_err("occupy", Some(path), None)?; + Ok(Continue) + }).log_ok(); + Ok(()) + }).log_ok(); + } + + pub fn unoccupy(&self) -> bool { + let mut ok = false; + Directory::open(self).and_then(|mut dir| { + ok = dir.pre_order_walk(|entry| { + let mut path = Utf8CStrBufArr::default(); + entry.resolve_path(&mut path)?; + let path = path.as_utf8_cstr(); + umount2( + path, + MntFlags::MNT_DETACH, + ).check_os_err("unoccupy", Some(path), None)?; + if entry.is_dir() { + Ok(Skip) + } else { + Ok(Continue) + } + }).is_ok(); + Ok(()) + }).log_ok(); + ok + } + } diff --git a/native/src/core/mount.rs b/native/src/core/mount.rs index 2ebb24c1c..3877aae04 100644 --- a/native/src/core/mount.rs +++ b/native/src/core/mount.rs @@ -221,7 +221,8 @@ pub fn revert_unmount(pid: i32) { // Unmount Magisk tmpfs and mounts from module files for info in parse_mount_info("self") { - if info.source == "magisk" || info.root.starts_with("/adb/modules") { + if info.source == "magisk" || info.root.starts_with("/adb/modules") || + (info.fs_type == "rootfs" && info.root.starts_with("/magisk")) { targets.push(info.target); } } diff --git a/native/src/init/init.rs b/native/src/init/init.rs index 8dfdabe80..7db0b3eac 100644 --- a/native/src/init/init.rs +++ b/native/src/init/init.rs @@ -3,9 +3,10 @@ use crate::logging::setup_klog; use crate::mount::is_rootfs; use crate::twostage::hexpatch_init_for_second_stage; use base::libc::{basename, getpid, mount, umask}; -use base::{LibcReturn, LoggedResult, ResultExt, cstr, info, raw_cstr}; +use base::{LibcReturn, LoggedResult, ResultExt, cstr, info, raw_cstr, nix, Utf8CStr}; use std::ffi::{CStr, c_char}; use std::ptr::null; +use base::nix::mount::MsFlags; impl MagiskInit { fn new(argv: *mut *mut c_char) -> Self { @@ -31,7 +32,7 @@ impl MagiskInit { fn first_stage(&self) { info!("First Stage Init"); - self.prepare_data(); + let rootfs_magisktmp = self.prepare_data(true); if !cstr!("/sdcard").exists() && !cstr!("/first_stage_ramdisk/sdcard").exists() { self.hijack_init_with_switch_root(); @@ -41,11 +42,28 @@ impl MagiskInit { // Fallback to hexpatch if /sdcard exists hexpatch_init_for_second_stage(true); } + + if rootfs_magisktmp { + info!("Occupy /data."); + cstr!("/data").occupy(); + } } fn second_stage(&mut self) { info!("Second Stage Init"); + if cstr!("/data").unoccupy() { + nix::mount::mount( + None::<&Utf8CStr>, + cstr!("/data"), + None::<&Utf8CStr>, + MsFlags::MS_REMOUNT, + Some(cstr!("size=100%")), + ) + .check_os_err("mount", Some("/data"), Some("tmpfs")) + .log_ok(); + } + cstr!("/init").unmount().ok(); cstr!("/system/bin/init").unmount().ok(); // just in case cstr!("/data/init").remove().ok(); @@ -71,7 +89,7 @@ impl MagiskInit { fn legacy_system_as_root(&mut self) { info!("Legacy SAR Init"); - self.prepare_data(); + self.prepare_data(false); let is_two_stage = self.mount_system_root(); if is_two_stage { hexpatch_init_for_second_stage(false); @@ -82,7 +100,7 @@ impl MagiskInit { fn rootfs(&mut self) { info!("RootFS Init"); - self.prepare_data(); + self.prepare_data(false); self.restore_ramdisk_init(); self.patch_rw_root(); } diff --git a/native/src/init/mount.rs b/native/src/init/mount.rs index d7f0a02fd..73a36b08a 100644 --- a/native/src/init/mount.rs +++ b/native/src/init/mount.rs @@ -73,22 +73,39 @@ pub(crate) fn is_rootfs() -> bool { } impl MagiskInit { - pub(crate) fn prepare_data(&self) { + pub(crate) fn prepare_data(&self, use_rootfs: bool) -> bool { debug!("Setup data tmp"); cstr!("/data").mkdir(0o755).log_ok(); - nix::mount::mount( - Some(cstr!("magisk")), - cstr!("/data"), - Some(cstr!("tmpfs")), - MsFlags::empty(), - Some(cstr!("mode=755")), - ) - .check_os_err("mount", Some("/data"), Some("tmpfs")) - .log_ok(); - cstr!("/init").copy_to(cstr!("/data/magiskinit")).ok(); - cstr!("/.backup").copy_to(cstr!("/data/.backup")).ok(); - cstr!("/overlay.d").copy_to(cstr!("/data/overlay.d")).ok(); + let mut rootfs_magisktmp = false; + + if use_rootfs { + cstr!("/magisk").mkdir(0o755).log_ok(); + rootfs_magisktmp = cstr!("/magisk").bind_mount_to(cstr!("/data"), false) + .is_ok(); + } + + if rootfs_magisktmp { + cstr!("/init").rename_to(cstr!("/magisk/magiskinit")).log_ok(); + cstr!("/.backup").copy_to(cstr!("/magisk/.backup")).ok(); + cstr!("/overlay.d").rename_to(cstr!("/magisk/overlay.d")).ok(); + } else { + nix::mount::mount( + Some(cstr!("magisk")), + cstr!("/data"), + Some(cstr!("tmpfs")), + MsFlags::empty(), + Some(cstr!("mode=755")), + ) + .check_os_err("mount", Some("/data"), Some("tmpfs")) + .log_ok(); + + cstr!("/init").copy_to(cstr!("/data/magiskinit")).ok(); + cstr!("/.backup").copy_to(cstr!("/data/.backup")).ok(); + cstr!("/overlay.d").copy_to(cstr!("/data/overlay.d")).ok(); + } + + rootfs_magisktmp } pub(crate) fn exec_init(&mut self) { diff --git a/native/src/init/twostage.rs b/native/src/init/twostage.rs index 0f2ad7775..1ca1130ec 100644 --- a/native/src/init/twostage.rs +++ b/native/src/init/twostage.rs @@ -84,20 +84,12 @@ impl MagiskInit { .log_ok(); debug!("Symlink /storage/self/primary -> /system/system/bin/init"); } - cstr!("/init").rename_to(cstr!("/sdcard")).log_ok(); - // First try to mount magiskinit from rootfs to workaround Samsung RKP - if cstr!("/sdcard") + // Binding mounting from rootfs is not supported before Linux 3.12 + cstr!("/sdcard").create(OFlag::O_RDONLY | OFlag::O_CLOEXEC, 0).log_ok(); + cstr!("/data/magiskinit") .bind_mount_to(cstr!("/sdcard"), false) - .is_ok() - { - debug!("Bind mount /sdcard -> /sdcard"); - } else { - // Binding mounting from rootfs is not supported before Linux 3.12 - cstr!("/data/magiskinit") - .bind_mount_to(cstr!("/sdcard"), false) - .log_ok(); - debug!("Bind mount /data/magiskinit -> /sdcard"); - } + .log_ok(); + debug!("Bind mount /data/magiskinit -> /sdcard"); } } diff --git a/native/src/sepolicy/rules.rs b/native/src/sepolicy/rules.rs index 0bc548de2..6bb28f981 100644 --- a/native/src/sepolicy/rules.rs +++ b/native/src/sepolicy/rules.rs @@ -110,7 +110,7 @@ impl SePolicy { allow(["kernel"], ["rootfs", "tmpfs"], ["chr_file"], ["write"]); // Allow magiskinit daemon to handle mock selinuxfs - allow(["kernel"], ["tmpfs"], ["fifo_file"], ["open", "read", "write"]); + allow(["kernel"], ["rootfs", "tmpfs"], ["fifo_file"], ["open", "read", "write"]); // For relabelling files allow(["rootfs"], ["labeledfs", "tmpfs"], ["filesystem"], ["associate"]);