diff --git a/userspace/ksud/Cargo.lock b/userspace/ksud/Cargo.lock index 11c6b942..b5d1bae8 100644 --- a/userspace/ksud/Cargo.lock +++ b/userspace/ksud/Cargo.lock @@ -82,9 +82,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64ct" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" @@ -763,9 +763,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" dependencies = [ "libc", ] @@ -1426,9 +1426,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.17" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ "serde", "time-core", @@ -1732,7 +1732,7 @@ dependencies = [ "hmac", "pbkdf2", "sha1", - "time 0.3.17", + "time 0.3.20", "zstd", ] @@ -1766,9 +1766,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.6+zstd.1.5.2" +version = "2.0.7+zstd.1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b" +checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" dependencies = [ "cc", "libc", diff --git a/userspace/ksud/src/defs.rs b/userspace/ksud/src/defs.rs index 71ec132a..8de511df 100644 --- a/userspace/ksud/src/defs.rs +++ b/userspace/ksud/src/defs.rs @@ -5,6 +5,7 @@ pub const WORKING_DIR: &str = concatcp!(ADB_DIR, "ksu/"); pub const BINARY_DIR: &str = concatcp!(WORKING_DIR, "bin/"); pub const KSURC_PATH: &str = concatcp!(WORKING_DIR, ".ksurc"); +pub const STOCK_MNT_ROOT: &str = concatcp!(WORKING_DIR, ".mnt"); pub const DAEMON_PATH: &str = concatcp!(ADB_DIR, "ksud"); #[cfg(target_os = "android")] diff --git a/userspace/ksud/src/mount.rs b/userspace/ksud/src/mount.rs index 40efeab6..eca448d6 100644 --- a/userspace/ksud/src/mount.rs +++ b/userspace/ksud/src/mount.rs @@ -12,6 +12,8 @@ use procfs::process::{MountInfo, Process}; #[cfg(any(target_os = "linux", target_os = "android"))] use std::collections::HashSet; +use crate::utils; + pub struct AutoMountExt4 { mnt: String, #[cfg(any(target_os = "linux", target_os = "android"))] @@ -167,7 +169,6 @@ impl StockOverlay { pub fn mount_all(&self) { unimplemented!() } - } #[cfg(any(target_os = "linux", target_os = "android"))] @@ -245,61 +246,92 @@ impl StockOverlay { pub struct StockMount { mnt: String, #[cfg(any(target_os = "linux", target_os = "android"))] - mountlist: proc_mounts::MountList, + mountlist: Vec<(proc_mounts::MountInfo, std::path::PathBuf)>, + rootmount: sys_mount::Mount, } #[cfg(any(target_os = "linux", target_os = "android"))] impl StockMount { pub fn new(mnt: &str) -> Result { let mountlist = proc_mounts::MountList::new()?; - Ok(Self { - mnt: mnt.to_string(), - mountlist, - }) - } - - fn get_target_mounts(&self) -> Vec<&proc_mounts::MountInfo> { - let mut mounts = self - .mountlist - .destination_starts_with(std::path::Path::new(&self.mnt)) + let mut mounts = mountlist + .destination_starts_with(std::path::Path::new(mnt)) .filter(|m| m.fstype != "overlay" && m.fstype != "rootfs") .collect::>(); mounts.sort_by(|a, b| b.dest.cmp(&a.dest)); // inverse order - mounts + + let mntroot = std::path::Path::new(crate::defs::STOCK_MNT_ROOT); + utils::ensure_dir_exists(&mntroot)?; + log::info!("stock mount root: {}", mntroot.display()); + + let rootdir = mntroot.join( + mnt.strip_prefix("/") + .ok_or(anyhow::anyhow!("invalid mnt: {}!", mnt))?, + ); + utils::ensure_dir_exists(&rootdir)?; + let rootmount = Mount::builder().fstype("tmpfs").mount("tmpfs", &rootdir)?; + + let mut ms = vec![]; + for m in mounts { + let dest = &m.dest; + if dest == std::path::Path::new(mnt) { + continue; + } + + let path = rootdir.join(dest.strip_prefix("/")?); + log::info!("rootdir: {}, path: {}", rootdir.display(), path.display()); + if dest.is_dir() { + utils::ensure_dir_exists(&path)?; + } else if dest.is_file() { + utils::ensure_file_exists(&path)?; + } else { + log::warn!("unknown file type: {:?}", dest); + } + log::info!("bind stock mount: {} -> {}", dest.display(), path.display()); + Mount::builder() + .flags(MountFlags::BIND) + .mount(&dest, &path)?; + + ms.push((m.clone(), path)); + } + + Ok(Self { + mnt: mnt.to_string(), + mountlist: ms, + rootmount, + }) } - pub fn remount(&self) -> Result<()> { - let mut mounts = self.get_target_mounts(); - mounts.reverse(); // remount it in order - log::info!("remount stock for {} : {:?}", self.mnt, mounts); - for m in mounts { - let src = std::fs::canonicalize(&m.source)?; + // Yes, we move self here! + pub fn remount(self) -> Result<()> { + log::info!("remount stock for {} : {:?}", self.mnt, self.mountlist); + let mut result = Ok(()); + for (m, src) in self.mountlist { + let dst = m.dest; - let src = src.to_str().ok_or(anyhow::anyhow!("Failed to get src"))?; - let dst = m - .dest - .to_str() - .ok_or(anyhow::anyhow!("Failed to get dst"))?; - - let fstype = m.fstype.as_str(); - let options = m.options.join(","); - - log::info!("begin remount: {src} -> {dst}"); - let result = std::process::Command::new("mount") - .arg("-t") - .arg(fstype) - .arg("-o") - .arg(options) - .arg(src) - .arg(dst) - .status(); - if let Err(e) = result { + log::info!("begin remount: {} -> {}", src.display(), dst.display()); + let mount_result = Mount::builder() + .flags(MountFlags::BIND | MountFlags::MOVE) + .mount(&src, &dst); + if let Err(e) = mount_result { log::error!("remount failed: {}", e); + result = Err(e); } else { - log::info!("remount {src} -> {dst} succeed!"); + log::info!( + "remount {}({}) -> {} succeed!", + m.source.display(), + src.display(), + dst.display() + ); } } - Ok(()) + + // umount the root tmpfs mount + if let Err(e) = self.rootmount.unmount(UnmountFlags::DETACH) { + log::warn!("umount root mount failed: {}", e); + } + + result } }