diff --git a/userspace/ksud/src/module.rs b/userspace/ksud/src/module.rs index 6f65e454..f34850be 100644 --- a/userspace/ksud/src/module.rs +++ b/userspace/ksud/src/module.rs @@ -11,6 +11,9 @@ use const_format::concatcp; use is_executable::is_executable; use java_properties::PropertiesIter; use log::{info, warn}; +#[cfg(any(target_os = "linux", target_os = "android"))] +use rustix::{fd::AsFd, fs::CWD, mount::*}; + use std::{ collections::HashMap, env::var as env_var, @@ -706,17 +709,53 @@ pub fn shrink_ksu_images() -> Result<()> { #[cfg(any(target_os = "linux", target_os = "android"))] pub fn link_module_for_manager(pid: i32, pkg: &str, mid: &str) -> Result<()> { - // switch to manager's mnt ns - utils::switch_mnt_ns(pid)?; - let target = PathBuf::from("/data/data").join(pkg).join("webroot"); - - // umount previous mount - let _ = mount::umount_dir(&target); - - let src = PathBuf::from(defs::MODULE_DIR) + let from = PathBuf::from(defs::MODULE_DIR) .join(mid) .join(defs::MODULE_WEB_DIR); - mount::bind_mount(src, &target)?; + + let to = PathBuf::from("/data/data").join(pkg).join("webroot"); + + if let Result::Ok(tree) = open_tree( + rustix::fs::CWD, + &from, + OpenTreeFlags::OPEN_TREE_CLOEXEC + | OpenTreeFlags::OPEN_TREE_CLONE + | OpenTreeFlags::AT_RECURSIVE, + ) { + switch_mnt_ns(pid)?; + + // umount previous mount + let _ = mount::umount_dir(&to); + + if let Err(e) = move_mount( + tree.as_fd(), + "", + CWD, + &to, + MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, + ) { + log::error!("move_mount failed: {}", e); + } + } else { + log::info!("fallback to bind mount"); + // switch to manager's mnt ns + utils::switch_mnt_ns(pid)?; + if !Path::new(&from).exists() { + // maybe it is umounted, mount it back + log::info!("module web dir not exists, try to mount it back."); + mount::AutoMountExt4::try_new(defs::MODULE_IMG, defs::MODULE_DIR, false) + .with_context(|| "mount module image failed".to_string())?; + } + + // umount previous mount + let _ = mount::umount_dir(&to); + + if let Err(e) = rustix::mount::mount(&from, &to, "", MountFlags::BIND | MountFlags::REC, "") + { + log::error!("mount failed: {}", e); + } + } + Ok(()) } diff --git a/userspace/ksud/src/mount.rs b/userspace/ksud/src/mount.rs index 25026ad4..615e626c 100644 --- a/userspace/ksud/src/mount.rs +++ b/userspace/ksud/src/mount.rs @@ -3,7 +3,6 @@ use anyhow::{anyhow, bail, Ok, Result}; #[cfg(any(target_os = "linux", target_os = "android"))] use anyhow::Context; #[cfg(any(target_os = "linux", target_os = "android"))] -#[cfg(any(target_os = "linux", target_os = "android"))] use rustix::{fd::AsFd, fs::CWD, mount::*}; use crate::defs::KSU_OVERLAY_SOURCE;