Skip to content

Commit

Permalink
ksud: allow to set upperdir and workdir for overlayfs
Browse files Browse the repository at this point in the history
  • Loading branch information
tiann committed Feb 1, 2024
1 parent aca505c commit 9f04482
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 12 deletions.
2 changes: 2 additions & 0 deletions userspace/ksud/src/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
16 changes: 12 additions & 4 deletions userspace/ksud/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,29 @@ use crate::{
utils::{self, ensure_clean_dir, ensure_dir_exists},
};

fn mount_partition(partition: &str, lowerdir: &Vec<String>) -> Result<()> {
fn mount_partition(partition_name: &str, lowerdir: &Vec<String>) -> 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() {
warn!("partition: {partition} is a symlink");
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<()> {
Expand Down
42 changes: 34 additions & 8 deletions userspace/ksud/src/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -81,21 +82,35 @@ pub fn umount_dir(src: impl AsRef<Path>) -> Result<()> {
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_overlayfs(lower_dirs: &[String], lowest: &str, dest: impl AsRef<Path>) -> Result<()> {
pub fn mount_overlayfs(
lower_dirs: &[String],
lowest: &str,
upperdir: Option<PathBuf>,
workdir: Option<PathBuf>,
dest: impl AsRef<Path>,
) -> Result<()> {
let lowerdir_config = lower_dirs
.iter()
.map(|s| s.as_ref())
.chain(std::iter::once(lowest))
.collect::<Vec<_>>()
.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())?;
Expand Down Expand Up @@ -180,15 +195,20 @@ 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)?;
}
Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn mount_overlay(root: &String, module_roots: &Vec<String>) -> Result<()> {
pub fn mount_overlay(
root: &String,
module_roots: &Vec<String>,
workdir: Option<PathBuf>,
upperdir: Option<PathBuf>,
) -> Result<()> {
info!("mount overlay for {}", root);
std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?;
let stock_root = ".";
Expand All @@ -208,7 +228,8 @@ pub fn mount_overlay(root: &String, module_roots: &Vec<String>) -> 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;
Expand Down Expand Up @@ -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<String>) -> Result<()> {
pub fn mount_overlay(
_root: &String,
_module_roots: &Vec<String>,
_workdir: Option<PathBuf>,
_upperdir: Option<PathBuf>,
) -> Result<()> {
unimplemented!()
}

Expand Down

0 comments on commit 9f04482

Please sign in to comment.