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:
18
userspace/ksud/Cargo.lock
generated
18
userspace/ksud/Cargo.lock
generated
@@ -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",
|
||||||
|
|||||||
@@ -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")]
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
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<()> {
|
// Yes, we move self here!
|
||||||
let mut mounts = self.get_target_mounts();
|
pub fn remount(self) -> Result<()> {
|
||||||
mounts.reverse(); // remount it in order
|
log::info!("remount stock for {} : {:?}", self.mnt, self.mountlist);
|
||||||
log::info!("remount stock for {} : {:?}", self.mnt, mounts);
|
let mut result = Ok(());
|
||||||
for m in mounts {
|
for (m, src) in self.mountlist {
|
||||||
let src = std::fs::canonicalize(&m.source)?;
|
let dst = m.dest;
|
||||||
|
|
||||||
let src = src.to_str().ok_or(anyhow::anyhow!("Failed to get src"))?;
|
log::info!("begin remount: {} -> {}", src.display(), dst.display());
|
||||||
let dst = m
|
let mount_result = Mount::builder()
|
||||||
.dest
|
.flags(MountFlags::BIND | MountFlags::MOVE)
|
||||||
.to_str()
|
.mount(&src, &dst);
|
||||||
.ok_or(anyhow::anyhow!("Failed to get dst"))?;
|
if let Err(e) = mount_result {
|
||||||
|
|
||||||
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);
|
log::error!("remount failed: {}", e);
|
||||||
|
result = Err(e);
|
||||||
} else {
|
} 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user