ksud: use move mount instead of remount for stock mounts

Because some stock mounts are difficult to remount it back, so we bind mount it to somewhere else before overlayfs mount. And then use move mount to mount it back.
This commit is contained in:
tiann
2023-04-11 20:32:08 +08:00
parent 5f04954a5c
commit a46d4ecd3e
3 changed files with 82 additions and 49 deletions

View File

@@ -82,9 +82,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.5.3" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bindgen" name = "bindgen"
@@ -763,9 +763,9 @@ dependencies = [
[[package]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.25" version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@@ -1426,9 +1426,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.17" version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
dependencies = [ dependencies = [
"serde", "serde",
"time-core", "time-core",
@@ -1732,7 +1732,7 @@ dependencies = [
"hmac", "hmac",
"pbkdf2", "pbkdf2",
"sha1", "sha1",
"time 0.3.17", "time 0.3.20",
"zstd", "zstd",
] ]
@@ -1766,9 +1766,9 @@ dependencies = [
[[package]] [[package]]
name = "zstd-sys" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b" checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",

View File

@@ -5,6 +5,7 @@ pub const WORKING_DIR: &str = concatcp!(ADB_DIR, "ksu/");
pub const BINARY_DIR: &str = concatcp!(WORKING_DIR, "bin/"); pub const BINARY_DIR: &str = concatcp!(WORKING_DIR, "bin/");
pub const KSURC_PATH: &str = concatcp!(WORKING_DIR, ".ksurc"); 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"); pub const DAEMON_PATH: &str = concatcp!(ADB_DIR, "ksud");
#[cfg(target_os = "android")] #[cfg(target_os = "android")]

View File

@@ -12,6 +12,8 @@ use procfs::process::{MountInfo, Process};
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use std::collections::HashSet; use std::collections::HashSet;
use crate::utils;
pub struct AutoMountExt4 { pub struct AutoMountExt4 {
mnt: String, mnt: String,
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -167,7 +169,6 @@ impl StockOverlay {
pub fn mount_all(&self) { pub fn mount_all(&self) {
unimplemented!() unimplemented!()
} }
} }
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -245,61 +246,92 @@ impl StockOverlay {
pub struct StockMount { pub struct StockMount {
mnt: String, mnt: String,
#[cfg(any(target_os = "linux", target_os = "android"))] #[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"))] #[cfg(any(target_os = "linux", target_os = "android"))]
impl StockMount { impl StockMount {
pub fn new(mnt: &str) -> Result<Self> { pub fn new(mnt: &str) -> Result<Self> {
let mountlist = proc_mounts::MountList::new()?; let mountlist = proc_mounts::MountList::new()?;
Ok(Self { let mut mounts = mountlist
mnt: mnt.to_string(), .destination_starts_with(std::path::Path::new(mnt))
mountlist,
})
}
fn get_target_mounts(&self) -> Vec<&proc_mounts::MountInfo> {
let mut mounts = self
.mountlist
.destination_starts_with(std::path::Path::new(&self.mnt))
.filter(|m| m.fstype != "overlay" && m.fstype != "rootfs") .filter(|m| m.fstype != "overlay" && m.fstype != "rootfs")
.collect::<Vec<_>>(); .collect::<Vec<_>>();
mounts.sort_by(|a, b| b.dest.cmp(&a.dest)); // inverse order mounts.sort_by(|a, b| b.dest.cmp(&a.dest)); // inverse order
mounts
}
pub fn remount(&self) -> Result<()> { let mntroot = std::path::Path::new(crate::defs::STOCK_MNT_ROOT);
let mut mounts = self.get_target_mounts(); utils::ensure_dir_exists(&mntroot)?;
mounts.reverse(); // remount it in order log::info!("stock mount root: {}", mntroot.display());
log::info!("remount stock for {} : {:?}", self.mnt, mounts);
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 { for m in mounts {
let src = std::fs::canonicalize(&m.source)?; let dest = &m.dest;
if dest == std::path::Path::new(mnt) {
continue;
}
let src = src.to_str().ok_or(anyhow::anyhow!("Failed to get src"))?; let path = rootdir.join(dest.strip_prefix("/")?);
let dst = m log::info!("rootdir: {}, path: {}", rootdir.display(), path.display());
.dest if dest.is_dir() {
.to_str() utils::ensure_dir_exists(&path)?;
.ok_or(anyhow::anyhow!("Failed to get dst"))?; } else if dest.is_file() {
utils::ensure_file_exists(&path)?;
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::error!("remount failed: {}", e);
} else { } else {
log::info!("remount {src} -> {dst} succeed!"); 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,
})
}
// 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;
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 {}({}) -> {} 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
} }
} }