diff --git a/userspace/ksud/src/mount.rs b/userspace/ksud/src/mount.rs index 6dd326c159cc..9fbbae69e139 100644 --- a/userspace/ksud/src/mount.rs +++ b/userspace/ksud/src/mount.rs @@ -13,6 +13,12 @@ use procfs::process::Process; use std::path::Path; use std::path::PathBuf; +macro_rules! null_arg { + () => { + unsafe { std::ffi::CStr::from_ptr(std::ptr::null()) } + }; +} + pub struct AutoMountExt4 { target: String, auto_umount: bool, @@ -59,18 +65,27 @@ pub fn mount_ext4(source: impl AsRef, target: impl AsRef) -> Result< let new_loopback = loopdev::LoopControl::open()?.next_free()?; new_loopback.with().attach(source)?; let lo = new_loopback.path().ok_or(anyhow!("no loop"))?; - let fs = fsopen("ext4", FsOpenFlags::FSOPEN_CLOEXEC)?; - let fs = fs.as_fd(); - fsconfig_set_string(fs, "source", lo)?; - fsconfig_create(fs)?; - let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; - move_mount( - mount.as_fd(), - "", - CWD, - target.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; + if let Result::Ok(fs) = fsopen("ext4", FsOpenFlags::FSOPEN_CLOEXEC) { + let fs = fs.as_fd(); + fsconfig_set_string(fs, "source", lo)?; + fsconfig_create(fs)?; + let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; + move_mount( + mount.as_fd(), + "", + CWD, + target.as_ref(), + MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, + )?; + } else { + mount( + lo, + target.as_ref(), + "ext4", + MountFlags::empty(), + null_arg!(), + )?; + } Ok(()) } @@ -102,43 +117,71 @@ pub fn mount_overlayfs( 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())?; + if let Result::Ok(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())?; + move_mount( + mount.as_fd(), + "", + CWD, + dest.as_ref(), + MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, + )?; + } else { + let mut data = format!("lowerdir={lowerdir_config}"); + if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) { + if upperdir.exists() && workdir.exists() { + data = format!( + "{data},upperdir={},workdir={}", + upperdir.display(), + workdir.display() + ); + } } + mount( + KSU_OVERLAY_SOURCE, + dest.as_ref(), + "overlay", + MountFlags::empty(), + data, + )?; } - fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; - fsconfig_create(fs)?; - let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; - move_mount( - mount.as_fd(), - "", - CWD, - dest.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; Ok(()) } #[cfg(any(target_os = "linux", target_os = "android"))] pub fn mount_tmpfs(dest: impl AsRef) -> Result<()> { info!("mount tmpfs on {}", dest.as_ref().display()); - let fs = fsopen("tmpfs", FsOpenFlags::FSOPEN_CLOEXEC)?; - let fs = fs.as_fd(); - fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; - fsconfig_create(fs)?; - let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; - move_mount( - mount.as_fd(), - "", - CWD, - dest.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; + if let Result::Ok(fs) = fsopen("tmpfs", FsOpenFlags::FSOPEN_CLOEXEC) { + let fs = fs.as_fd(); + fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; + fsconfig_create(fs)?; + let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; + move_mount( + mount.as_fd(), + "", + CWD, + dest.as_ref(), + MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, + )?; + } else { + mount( + KSU_OVERLAY_SOURCE, + dest.as_ref(), + "tmpfs", + MountFlags::empty(), + null_arg!(), + )?; + } Ok(()) } @@ -149,20 +192,29 @@ fn bind_mount(from: impl AsRef, to: impl AsRef) -> Result<()> { from.as_ref().display(), to.as_ref().display() ); - let tree = open_tree( + if let Result::Ok(tree) = open_tree( CWD, from.as_ref(), OpenTreeFlags::OPEN_TREE_CLOEXEC | OpenTreeFlags::OPEN_TREE_CLONE | OpenTreeFlags::AT_RECURSIVE, - )?; - move_mount( - tree.as_fd(), - "", - CWD, - to.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; + ) { + move_mount( + tree.as_fd(), + "", + CWD, + to.as_ref(), + MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, + )?; + } else { + mount( + from.as_ref(), + to.as_ref(), + null_arg!(), + MountFlags::BIND | MountFlags::REC, + null_arg!(), + )?; + } Ok(()) }