From b76d973f3af4b01a33c7f852599410fd530003a8 Mon Sep 17 00:00:00 2001 From: tiann Date: Tue, 21 Feb 2023 20:21:34 +0800 Subject: [PATCH] ksud: restore stock mount after overlay mount. close #233 --- userspace/ksud/Cargo.lock | 19 ++++++++++ userspace/ksud/Cargo.toml | 1 + userspace/ksud/src/event.rs | 26 +++++++++++++- userspace/ksud/src/mount.rs | 70 +++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) diff --git a/userspace/ksud/Cargo.lock b/userspace/ksud/Cargo.lock index 0f369ea4..07aac687 100644 --- a/userspace/ksud/Cargo.lock +++ b/userspace/ksud/Cargo.lock @@ -800,6 +800,7 @@ dependencies = [ "libc", "log", "nom", + "proc-mounts", "procfs", "regex", "retry", @@ -986,6 +987,15 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +[[package]] +name = "partition-identity" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa925f9becb532d758b0014b472c576869910929cf4c3f8054b386f19ab9e21" +dependencies = [ + "thiserror", +] + [[package]] name = "password-hash" version = "0.4.2" @@ -1072,6 +1082,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-mounts" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d652f8435d0ab70bf4f3590a6a851d59604831a458086541b95238cc51ffcf2" +dependencies = [ + "partition-identity", +] + [[package]] name = "procfs" version = "0.15.1" diff --git a/userspace/ksud/Cargo.toml b/userspace/ksud/Cargo.toml index cfc18d2b..c1fd4b64 100644 --- a/userspace/ksud/Cargo.toml +++ b/userspace/ksud/Cargo.toml @@ -31,6 +31,7 @@ rust-embed = { version = "6.4.2", features = [ "debug-embed", "compression", # must clean build after updating binaries ] } +proc-mounts = "0.3" [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] sys-mount = { git = "https://github.com/tiann/sys-mount" } diff --git a/userspace/ksud/src/event.rs b/userspace/ksud/src/event.rs index 4bc3481e..438d95ec 100644 --- a/userspace/ksud/src/event.rs +++ b/userspace/ksud/src/event.rs @@ -18,6 +18,19 @@ fn mount_partition(partition: &str, lowerdir: &mut Vec) -> Result<()> { warn!("partition: {partition} is a symlink"); return Ok(()); } + + // handle stock mounts under /partition, we should restore the mount point after overlay + let stock_mount = mount::StockMount::new(&format!("/{partition}/")) + .with_context(|| format!("get stock mount of partition: {partition} failed"))?; + let result = stock_mount.umount(); + if result.is_err() { + let remount_result = stock_mount.remount(); + if remount_result.is_err() { + log::error!("remount stock mount of failed: {:?}", remount_result); + } + bail!("umount stock mount of failed: {:?}", result); + } + // add /partition as the lowerest dir let lowest_dir = format!("/{partition}"); lowerdir.push(lowest_dir.clone()); @@ -25,7 +38,18 @@ fn mount_partition(partition: &str, lowerdir: &mut Vec) -> Result<()> { let lowerdir = lowerdir.join(":"); info!("partition: {partition} lowerdir: {lowerdir}"); - mount::mount_overlay(&lowerdir, &lowest_dir) + let result = mount::mount_overlay(&lowerdir, &lowest_dir); + + if result.is_ok() && stock_mount.remount().is_err() { + // if mount overlay ok but stock remount failed, we should umount overlay + warn!("remount stock mount of failed, umount overlay {lowest_dir} now"); + if mount::umount_dir(&lowest_dir).is_err() { + warn!("umount overlay {lowest_dir} failed"); + } + } + + result + } pub fn mount_systemlessly(module_dir: &str) -> Result<()> { diff --git a/userspace/ksud/src/mount.rs b/userspace/ksud/src/mount.rs index c36eebc3..d4d8c235 100644 --- a/userspace/ksud/src/mount.rs +++ b/userspace/ksud/src/mount.rs @@ -252,3 +252,73 @@ impl StockOverlay { } } } + +// some ROMs mount device(ext4,exfat) to /vendor, when we do overlay mount, it will overlay +// the stock mounts, these mounts include bt_firmware, wifi_firmware, etc. +// so we to remount these mounts when we do overlay mount. +// this is a workaround, we should find a better way to do this. +#[derive(Debug)] +pub struct StockMount { + mnt: String, + mountlist: proc_mounts::MountList, +} + +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 mounts = self + .mountlist + .destination_starts_with(&std::path::Path::new(&self.mnt)) + .filter(|m| m.fstype != "overlay"); + mounts.collect() + } + + pub fn umount(&self) -> Result<()> { + let mounts = self.get_target_mounts(); + log::info!("stock mount for {} : {:?}", self.mnt, mounts); + for m in mounts { + let dst = m + .dest + .to_str() + .ok_or(anyhow::anyhow!("Failed to get dst"))?; + umount_dir(dst)?; + log::info!("umount: {:?}", m); + } + Ok(()) + } + + pub fn remount(&self) -> Result<()> { + let mounts = self.get_target_mounts(); + for m in mounts { + let src = std::fs::canonicalize(&m.source)?; + + 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!("mount: {:?}", m); + std::process::Command::new("mount") + .arg("-t") + .arg(fstype) + .arg("-o") + .arg(options) + .arg(src) + .arg(dst) + .status() + .with_context(|| format!("Failed to mount {:?}", m))?; + } + Ok(()) + } +}