Migrate prepare_modules to Rust

This commit is contained in:
topjohnwu
2025-08-02 13:53:35 -07:00
committed by John Wu
parent 959430e030
commit 7961be5cfa
7 changed files with 63 additions and 42 deletions

View File

@@ -309,7 +309,7 @@ impl Directory {
self.pre_order_walk_impl(&mut f)
}
pub fn remove_all(&mut self) -> OsResultStatic<()> {
pub fn remove_all(mut self) -> OsResultStatic<()> {
self.post_order_walk(|e| {
e.unlink()?;
Ok(WalkResult::Continue)

View File

@@ -227,7 +227,7 @@ impl Utf8CStr {
pub fn remove_all(&self) -> OsResultStatic<()> {
let attr = self.get_attr()?;
if attr.is_dir() {
let mut dir = Directory::try_from(open_fd(self, O_RDONLY | O_CLOEXEC, 0)?)?;
let dir = Directory::try_from(open_fd(self, O_RDONLY | O_CLOEXEC, 0)?)?;
dir.remove_all()?;
}
Ok(self.remove()?)

View File

@@ -5,7 +5,7 @@ use crate::ffi::{
exec_module_scripts, get_magisk_tmp, initialize_denylist, setup_magisk_env,
};
use crate::logging::{magisk_logging, setup_logfile, start_log_daemon};
use crate::mount::{clean_mounts, setup_module_mount, setup_preinit_dir};
use crate::mount::{clean_mounts, setup_preinit_dir};
use crate::package::ManagerInfo;
use crate::selinux::restore_tmpcon;
use crate::su::SuInfo;
@@ -144,10 +144,7 @@ impl MagiskD {
Ordering::Release,
);
initialize_denylist();
setup_module_mount();
let modules = self.load_modules();
self.module_list.set(modules).ok();
self.apply_modules();
self.handle_modules();
clean_mounts();
false

View File

@@ -11,32 +11,6 @@ using namespace std;
* Filesystem operations
************************/
static void prepare_modules() {
// Upgrade modules
if (auto dir = open_dir(MODULEUPGRADE); dir) {
int ufd = dirfd(dir.get());
int mfd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC);
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (entry->d_type == DT_DIR) {
// Cleanup old module if exists
if (faccessat(mfd, entry->d_name, F_OK, 0) == 0) {
int modfd = xopenat(mfd, entry->d_name, O_RDONLY | O_CLOEXEC);
if (faccessat(modfd, "disable", F_OK, 0) == 0) {
auto disable = entry->d_name + "/disable"s;
close(xopenat(ufd, disable.data(), O_RDONLY | O_CREAT | O_CLOEXEC, 0));
}
frm_rf(modfd);
unlinkat(mfd, entry->d_name, AT_REMOVEDIR);
}
LOGI("Upgrade / New module: %s\n", entry->d_name);
renameat(ufd, entry->d_name, mfd, entry->d_name);
}
}
close(mfd);
rm_rf(MODULEUPGRADE);
}
}
template<typename Func>
static void foreach_module(Func fn) {
auto dir = open_dir(MODULEROOT);
@@ -135,7 +109,6 @@ static rust::Vec<ModuleInfo> collect_modules(bool zygisk_enabled, bool open_zygi
rust::Vec<ModuleInfo> MagiskD::load_modules() const noexcept {
bool zygisk = zygisk_enabled();
prepare_modules();
exec_module_scripts("post-fs-data", collect_modules(zygisk, false));
// Recollect modules (module scripts could remove itself)
auto list = collect_modules(zygisk, true);

View File

@@ -1,13 +1,15 @@
use crate::consts::{MODULEMNT, MODULEROOT, WORKERDIR};
use crate::consts::{MODULEMNT, MODULEROOT, MODULEUPGRADE, WORKERDIR};
use crate::daemon::MagiskD;
use crate::ffi::{get_magisk_tmp, get_zygisk_lib_name};
use crate::ffi::{ModuleInfo, get_magisk_tmp, get_zygisk_lib_name};
use crate::load_prop_file;
use crate::mount::setup_module_mount;
use base::{
Directory, FsPathBuilder, LoggedResult, OsResultStatic, ResultExt, Utf8CStr, Utf8CStrBuf,
Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, warn,
Directory, FsPathBuilder, LibcReturn, LoggedResult, OsResultStatic, ResultExt, Utf8CStr,
Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, warn,
};
use libc::{MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
use libc::{AT_REMOVEDIR, MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
use std::collections::BTreeMap;
use std::os::fd::AsRawFd;
use std::path::{Component, Path};
const MAGISK_BIN_INJECT_PARTITIONS: [&Utf8CStr; 4] = [
@@ -548,8 +550,48 @@ fn inject_zygisk_bins(system: &mut FsNode) {
}
}
fn prepare_modules() -> LoggedResult<()> {
let mut upgrade = Directory::open(cstr!(MODULEUPGRADE))?;
let ufd = upgrade.as_raw_fd();
let root = Directory::open(cstr!(MODULEROOT))?;
while let Some(ref e) = upgrade.read()? {
if !e.is_dir() {
continue;
}
let module_name = e.name();
let mut disable = false;
// Cleanup old module if exists
if root.contains_path(module_name) {
let module = root.open_as_dir_at(module_name)?;
// If the old module is disabled, we need to also disable the new one
disable = module.contains_path(cstr!("disable"));
module.remove_all()?;
root.unlink_at(module_name, AT_REMOVEDIR)?;
}
info!("Upgrade / New module: {module_name}");
unsafe {
libc::renameat(
ufd,
module_name.as_ptr(),
root.as_raw_fd(),
module_name.as_ptr(),
)
.check_os_err("renameat", Some(module_name), None)?;
}
if disable {
let path = cstr::buf::default()
.join_path(module_name)
.join_path("disable");
let _ = root.open_as_file_at(&path, O_RDONLY | O_CREAT | O_CLOEXEC, 0)?;
}
}
upgrade.remove_all()?;
cstr!(MODULEUPGRADE).remove()?;
Ok(())
}
impl MagiskD {
pub fn apply_modules(&self) {
fn apply_modules(&self, module_list: &[ModuleInfo]) {
let mut system = FsNode::new_dir();
// Build all the base "prefix" paths
@@ -578,7 +620,7 @@ impl MagiskD {
// In this step, there is zero logic applied during tree construction; we simply collect and
// record the union of all module filesystem trees under each of their /system directory.
for info in self.module_list.get().iter().flat_map(|v| v.iter()) {
for info in module_list {
let mut module_paths = root_paths.append(&info.name);
{
// Read props
@@ -656,4 +698,12 @@ impl MagiskD {
root.commit(path, true).log_ok();
}
}
pub fn handle_modules(&self) {
setup_module_mount();
prepare_modules().ok();
let modules = self.load_modules();
self.apply_modules(&modules);
self.module_list.set(modules).ok();
}
}

View File

@@ -15,6 +15,7 @@ pub const LOGFILE: &str = "/cache/magisk.log";
// data paths
pub const SECURE_DIR: &str = "/data/adb";
pub const MODULEROOT: &str = concatcp!(SECURE_DIR, "/modules");
pub const MODULEUPGRADE: &str = concatcp!(SECURE_DIR, "/modules_update");
pub const DATABIN: &str = concatcp!(SECURE_DIR, "/magisk");
pub const MAGISKDB: &str = concatcp!(SECURE_DIR, "/magisk.db");

View File

@@ -21,7 +21,7 @@ pub(crate) fn switch_root(path: &Utf8CStr) {
let res: LoggedResult<()> = try {
debug!("Switch root to {}", path);
let mut mounts = BTreeSet::new();
let mut rootfs = Directory::open(cstr!("/"))?;
let rootfs = Directory::open(cstr!("/"))?;
for info in parse_mount_info("self") {
if info.target == "/" || info.target.as_str() == path.as_str() {
continue;