From 9f04482b90712cd1e7fa03fab45af5876307bc10 Mon Sep 17 00:00:00 2001 From: weishu Date: Thu, 1 Feb 2024 18:02:10 +0800 Subject: [PATCH] ksud: allow to set upperdir and workdir for overlayfs --- userspace/ksud/src/defs.rs | 2 ++ userspace/ksud/src/event.rs | 16 ++++++++++---- userspace/ksud/src/mount.rs | 42 ++++++++++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/userspace/ksud/src/defs.rs b/userspace/ksud/src/defs.rs index d00c64d4..d967b02f 100644 --- a/userspace/ksud/src/defs.rs +++ b/userspace/ksud/src/defs.rs @@ -25,6 +25,8 @@ pub const MODULE_UPDATE_TMP_IMG: &str = concatcp!(WORKING_DIR, "update_tmp.img") // warning: this directory should not change, or you need to change the code in module_installer.sh!!! pub const MODULE_UPDATE_TMP_DIR: &str = concatcp!(ADB_DIR, "modules_update/"); +pub const SYSTEM_RW_DIR: &str = concatcp!(MODULE_DIR, ".rw/"); + pub const TEMP_DIR: &str = "/debug_ramdisk"; pub const TEMP_DIR_LEGACY: &str = "/sbin"; diff --git a/userspace/ksud/src/event.rs b/userspace/ksud/src/event.rs index c50fb7e9..84b709d9 100644 --- a/userspace/ksud/src/event.rs +++ b/userspace/ksud/src/event.rs @@ -10,13 +10,13 @@ use crate::{ utils::{self, ensure_clean_dir, ensure_dir_exists}, }; -fn mount_partition(partition: &str, lowerdir: &Vec) -> Result<()> { +fn mount_partition(partition_name: &str, lowerdir: &Vec) -> Result<()> { if lowerdir.is_empty() { - warn!("partition: {partition} lowerdir is empty"); + warn!("partition: {partition_name} lowerdir is empty"); return Ok(()); } - let partition = format!("/{partition}"); + let partition = format!("/{partition_name}"); // if /partition is a symlink and linked to /system/partition, then we don't need to overlay it separately if Path::new(&partition).read_link().is_ok() { @@ -24,7 +24,15 @@ fn mount_partition(partition: &str, lowerdir: &Vec) -> Result<()> { return Ok(()); } - mount::mount_overlay(&partition, lowerdir) + let mut workdir = None; + let mut upperdir = None; + let system_rw_dir = Path::new(defs::SYSTEM_RW_DIR); + if system_rw_dir.exists() { + workdir = Some(system_rw_dir.join(partition_name).join("workdir")); + upperdir = Some(system_rw_dir.join(partition_name).join("upperdir")); + } + + mount::mount_overlay(&partition, lowerdir, workdir, upperdir) } pub fn mount_systemlessly(module_dir: &str) -> Result<()> { diff --git a/userspace/ksud/src/mount.rs b/userspace/ksud/src/mount.rs index 6ac3ed7c..0ebe8866 100644 --- a/userspace/ksud/src/mount.rs +++ b/userspace/ksud/src/mount.rs @@ -11,6 +11,7 @@ use log::{info, warn}; #[cfg(any(target_os = "linux", target_os = "android"))] use procfs::process::Process; use std::path::Path; +use std::path::PathBuf; pub struct AutoMountExt4 { target: String, @@ -81,7 +82,13 @@ pub fn umount_dir(src: impl AsRef) -> Result<()> { } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn mount_overlayfs(lower_dirs: &[String], lowest: &str, dest: impl AsRef) -> Result<()> { +pub fn mount_overlayfs( + lower_dirs: &[String], + lowest: &str, + upperdir: Option, + workdir: Option, + dest: impl AsRef, +) -> Result<()> { let lowerdir_config = lower_dirs .iter() .map(|s| s.as_ref()) @@ -89,13 +96,21 @@ pub fn mount_overlayfs(lower_dirs: &[String], lowest: &str, dest: impl AsRef>() .join(":"); info!( - "mount overlayfs on {}, options={}", - dest.as_ref().display(), - lowerdir_config + "mount overlayfs on {:?}, lowerdir={}, upperdir={:?}, workdir={:?}", + dest.as_ref(), + lowerdir_config, + upperdir, + workdir ); let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?; let fs = fs.as_fd(); fsconfig_set_string(fs, "lowerdir", lowerdir_config)?; + if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) { + if upperdir.exists() && workdir.exists() { + fsconfig_set_string(fs, "upperdir", upperdir.display().to_string())?; + fsconfig_set_string(fs, "workdir", workdir.display().to_string())?; + } + } fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; fsconfig_create(fs)?; let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; @@ -180,7 +195,7 @@ fn mount_overlay_child( return Ok(()); } // merge modules and stock - if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, mount_point) { + if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, None, None, mount_point) { warn!("failed: {:#}, fallback to bind mount", e); bind_mount(stock_root, mount_point)?; } @@ -188,7 +203,12 @@ fn mount_overlay_child( } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn mount_overlay(root: &String, module_roots: &Vec) -> Result<()> { +pub fn mount_overlay( + root: &String, + module_roots: &Vec, + workdir: Option, + upperdir: Option, +) -> Result<()> { info!("mount overlay for {}", root); std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?; let stock_root = "."; @@ -208,7 +228,8 @@ pub fn mount_overlay(root: &String, module_roots: &Vec) -> Result<()> { mount_seq.sort(); mount_seq.dedup(); - mount_overlayfs(module_roots, root, root).with_context(|| "mount overlayfs for root failed")?; + mount_overlayfs(module_roots, root, upperdir, workdir, root) + .with_context(|| "mount overlayfs for root failed")?; for mount_point in mount_seq.iter() { let Some(mount_point) = mount_point else { continue; @@ -241,7 +262,12 @@ pub fn umount_dir(_src: &str) -> Result<()> { } #[cfg(not(any(target_os = "linux", target_os = "android")))] -pub fn mount_overlay(_dest: &String, _lower_dirs: &Vec) -> Result<()> { +pub fn mount_overlay( + _root: &String, + _module_roots: &Vec, + _workdir: Option, + _upperdir: Option, +) -> Result<()> { unimplemented!() }