Migrate setup_magisk_env to Rust

This commit is contained in:
topjohnwu
2025-09-14 22:12:48 -07:00
committed by John Wu
parent aab8344058
commit 7057d4c7f1
6 changed files with 104 additions and 73 deletions

View File

@@ -18,7 +18,6 @@ use std::fmt::Display;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write}; use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ops::Deref;
use std::os::fd::{AsFd, BorrowedFd}; use std::os::fd::{AsFd, BorrowedFd};
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsRawFd, OwnedFd, RawFd}; use std::os::unix::io::{AsRawFd, OwnedFd, RawFd};
@@ -307,17 +306,12 @@ impl Utf8CStr {
pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> { pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> {
if !attr.is_symlink() if !attr.is_symlink()
&& let Err(e) = nix::sys::stat::fchmodat( && let Err(e) = self.follow_link().chmod((attr.st.st_mode & 0o777).as_())
AT_FDCWD,
self,
Mode::from_bits_truncate((attr.st.st_mode & 0o777).as_()),
FchmodatFlags::FollowSymlink,
)
{ {
// Double check if self is symlink before reporting error // Double check if self is symlink before reporting error
let self_attr = self.get_attr()?; let self_attr = self.get_attr()?;
if !self_attr.is_symlink() { if !self_attr.is_symlink() {
return Err(OsError::new(e, "chmod", Some(self), None)); return Err(e);
} }
} }
@@ -521,13 +515,27 @@ impl Utf8CStr {
impl FsPathFollow { impl FsPathFollow {
pub fn exists(&self) -> bool { pub fn exists(&self) -> bool {
nix::unistd::access(self.deref(), AccessFlags::F_OK).is_ok() nix::unistd::access(self.as_utf8_cstr(), AccessFlags::F_OK).is_ok()
}
pub fn chmod(&self, mode: mode_t) -> OsResult<'_, ()> {
nix::sys::stat::fchmodat(
AT_FDCWD,
self.as_utf8_cstr(),
Mode::from_bits_truncate(mode),
FchmodatFlags::FollowSymlink,
)
.check_os_err("chmod", Some(self), None)
} }
pub fn get_attr(&self) -> OsResult<'_, FileAttr> { pub fn get_attr(&self) -> OsResult<'_, FileAttr> {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut attr = FileAttr { let mut attr = FileAttr {
st: nix::sys::stat::stat(self.deref()).into_os_result("lstat", Some(self), None)?, st: nix::sys::stat::stat(self.as_utf8_cstr()).into_os_result(
"lstat",
Some(self),
None,
)?,
#[cfg(feature = "selinux")] #[cfg(feature = "selinux")]
con: cstr::buf::new(), con: cstr::buf::new(),
}; };
@@ -537,16 +545,10 @@ impl FsPathFollow {
} }
pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> { pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> {
nix::sys::stat::fchmodat( self.chmod((attr.st.st_mode & 0o777).as_())?;
AT_FDCWD,
self.deref(),
Mode::from_bits_truncate((attr.st.st_mode & 0o777).as_()),
FchmodatFlags::FollowSymlink,
)
.check_os_err("chmod", Some(self), None)?;
nix::unistd::chown( nix::unistd::chown(
self.deref(), self.as_utf8_cstr(),
Some(Uid::from(attr.st.st_uid)), Some(Uid::from(attr.st.st_uid)),
Some(Gid::from(attr.st.st_gid)), Some(Gid::from(attr.st.st_gid)),
) )

View File

@@ -214,53 +214,6 @@ int connect_daemon(int req, bool create) {
return fd; return fd;
} }
bool setup_magisk_env() {
char buf[4096];
LOGI("* Initializing Magisk environment\n");
ssprintf(buf, sizeof(buf), "%s/0/%s/install", APP_DATA_DIR, JAVA_PACKAGE_NAME);
// Alternative binaries paths
const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf };
for (auto alt : alt_bin) {
if (access(alt, F_OK) == 0) {
rm_rf(DATABIN);
cp_afc(alt, DATABIN);
rm_rf(alt);
}
}
rm_rf("/cache/data_adb");
// Directories in /data/adb
chmod(SECURE_DIR, 0700);
xmkdir(DATABIN, 0755);
xmkdir(MODULEROOT, 0755);
xmkdir(SECURE_DIR "/post-fs-data.d", 0755);
xmkdir(SECURE_DIR "/service.d", 0755);
restorecon();
if (access(DATABIN "/busybox", X_OK))
return false;
ssprintf(buf, sizeof(buf), "%s/" BBPATH "/busybox", get_magisk_tmp());
mkdir(dirname(buf), 0755);
cp_afc(DATABIN "/busybox", buf);
exec_command_async(buf, "--install", "-s", dirname(buf));
// magisk32 and magiskpolicy are not installed into ramdisk and has to be copied
// from data to magisk tmp
if (access(DATABIN "/magisk32", X_OK) == 0) {
ssprintf(buf, sizeof(buf), "%s/magisk32", get_magisk_tmp());
cp_afc(DATABIN "/magisk32", buf);
}
if (access(DATABIN "/magiskpolicy", X_OK) == 0) {
ssprintf(buf, sizeof(buf), "%s/magiskpolicy", get_magisk_tmp());
cp_afc(DATABIN "/magiskpolicy", buf);
}
return true;
}
void unlock_blocks() { void unlock_blocks() {
int fd, dev, OFF = 0; int fd, dev, OFF = 0;

View File

@@ -1,19 +1,19 @@
use crate::UCred; use crate::UCred;
use crate::consts::{ use crate::consts::{
MAGISK_FULL_VER, MAGISK_PROC_CON, MAGISK_VER_CODE, MAGISK_VERSION, MAIN_CONFIG, ROOTMNT, APP_PACKAGE_NAME, BBPATH, DATABIN, MAGISK_FULL_VER, MAGISK_PROC_CON, MAGISK_VER_CODE,
ROOTOVL, SECURE_DIR, MAGISK_VERSION, MAIN_CONFIG, MODULEROOT, ROOTMNT, ROOTOVL, SECURE_DIR,
}; };
use crate::db::Sqlite3; use crate::db::Sqlite3;
use crate::ffi::{ use crate::ffi::{
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, denylist_handler, exec_common_scripts, DbEntryKey, ModuleInfo, RequestCode, check_key_combo, denylist_handler, exec_common_scripts,
exec_module_scripts, get_magisk_tmp, initialize_denylist, scan_deny_apps, setup_magisk_env, exec_module_scripts, get_magisk_tmp, initialize_denylist, scan_deny_apps,
}; };
use crate::logging::{android_logging, magisk_logging, setup_logfile, start_log_daemon}; use crate::logging::{android_logging, magisk_logging, setup_logfile, start_log_daemon};
use crate::module::{disable_modules, remove_modules}; use crate::module::{disable_modules, remove_modules};
use crate::mount::{clean_mounts, setup_preinit_dir}; use crate::mount::{clean_mounts, setup_preinit_dir};
use crate::package::ManagerInfo; use crate::package::ManagerInfo;
use crate::resetprop::{get_prop, set_prop}; use crate::resetprop::{get_prop, set_prop};
use crate::selinux::restore_tmpcon; use crate::selinux::{restore_tmpcon, restorecon};
use crate::socket::IpcWrite; use crate::socket::IpcWrite;
use crate::su::SuInfo; use crate::su::SuInfo;
use crate::zygisk::ZygiskState; use crate::zygisk::ZygiskState;
@@ -32,7 +32,7 @@ use std::fmt::Write as FmtWrite;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Write}; use std::io::{BufReader, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd, OwnedFd}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd, OwnedFd};
use std::process::{Command, exit}; use std::process::{Command, Stdio, exit};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Mutex, OnceLock}; use std::sync::{Mutex, OnceLock};
@@ -106,6 +106,83 @@ impl MagiskD {
} }
} }
fn setup_magisk_env(&self) -> bool {
info!("* Initializing Magisk environment");
let mut buf = cstr::buf::default();
let app_bin_dir = buf
.append_path(self.app_data_dir())
.append_path("0")
.append_path(APP_PACKAGE_NAME)
.append_path("install");
// Alternative binaries paths
let alt_bin_dirs = &[
cstr!("/cache/data_adb/magisk"),
cstr!("/data/magisk"),
app_bin_dir,
];
for dir in alt_bin_dirs {
if dir.exists() {
cstr!(DATABIN).remove_all().ok();
dir.copy_to(cstr!(DATABIN)).ok();
dir.remove_all().ok();
}
}
cstr!("/cache/data_adb").remove_all().ok();
// Directories in /data/adb
cstr!(SECURE_DIR).follow_link().chmod(0o700).log_ok();
cstr!(DATABIN).mkdir(0o755).log_ok();
cstr!(MODULEROOT).mkdir(0o755).log_ok();
cstr!(concatcp!(SECURE_DIR, "/post-fs-data.d"))
.mkdir(0o755)
.log_ok();
cstr!(concatcp!(SECURE_DIR, "/service.d"))
.mkdir(0o755)
.log_ok();
restorecon();
let busybox = cstr!(concatcp!(DATABIN, "/busybox"));
if !busybox.exists() {
return false;
}
let tmp_bb = buf.append_path(get_magisk_tmp()).append_path(BBPATH);
tmp_bb.mkdirs(0o755).ok();
tmp_bb.append_path("busybox");
tmp_bb.follow_link().chmod(0o755).log_ok();
busybox.copy_to(tmp_bb).ok();
// Install busybox applets
Command::new(&tmp_bb)
.arg("--install")
.arg("-s")
.arg(tmp_bb.parent_dir().unwrap())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.log_ok();
// magisk32 and magiskpolicy are not installed into ramdisk and has to be copied
// from data to magisk tmp
let magisk32 = cstr!(concatcp!(DATABIN, "/magisk32"));
if magisk32.exists() {
let tmp = buf.append_path(get_magisk_tmp()).append_path("magisk32");
magisk32.copy_to(tmp).log_ok();
}
let magiskpolicy = cstr!(concatcp!(DATABIN, "/magiskpolicy"));
if magiskpolicy.exists() {
let tmp = buf
.append_path(get_magisk_tmp())
.append_path("magiskpolicy");
magiskpolicy.copy_to(tmp).log_ok();
}
true
}
fn post_fs_data(&self) -> bool { fn post_fs_data(&self) -> bool {
setup_logfile(); setup_logfile();
info!("** post-fs-data mode running"); info!("** post-fs-data mode running");
@@ -125,7 +202,7 @@ impl MagiskD {
self.prune_su_access(); self.prune_su_access();
if !setup_magisk_env() { if !self.setup_magisk_env() {
error!("* Magisk environment incomplete, abort"); error!("* Magisk environment incomplete, abort");
return true; return true;
} }

View File

@@ -37,7 +37,6 @@ struct ModuleInfo;
int connect_daemon(int req, bool create = false); int connect_daemon(int req, bool create = false);
const char *get_magisk_tmp(); const char *get_magisk_tmp();
void unlock_blocks(); void unlock_blocks();
bool setup_magisk_env();
bool check_key_combo(); bool check_key_combo();
template<typename T> requires(std::is_trivially_copyable_v<T>) template<typename T> requires(std::is_trivially_copyable_v<T>)

View File

@@ -137,7 +137,6 @@ pub mod ffi {
fn get_magisk_tmp() -> Utf8CStrRef<'static>; fn get_magisk_tmp() -> Utf8CStrRef<'static>;
#[cxx_name = "resolve_preinit_dir_rs"] #[cxx_name = "resolve_preinit_dir_rs"]
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String; fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
fn setup_magisk_env() -> bool;
fn check_key_combo() -> bool; fn check_key_combo() -> bool;
#[cxx_name = "exec_script_rs"] #[cxx_name = "exec_script_rs"]
fn exec_script(script: Utf8CStrRef); fn exec_script(script: Utf8CStrRef);

View File

@@ -25,6 +25,7 @@ pub const MAIN_CONFIG: &str = concatcp!(INTERNAL_DIR, "/config");
pub const PREINITMIRR: &str = concatcp!(INTERNAL_DIR, "/preinit"); pub const PREINITMIRR: &str = concatcp!(INTERNAL_DIR, "/preinit");
pub const MODULEMNT: &str = concatcp!(INTERNAL_DIR, "/modules"); pub const MODULEMNT: &str = concatcp!(INTERNAL_DIR, "/modules");
pub const WORKERDIR: &str = concatcp!(INTERNAL_DIR, "/worker"); pub const WORKERDIR: &str = concatcp!(INTERNAL_DIR, "/worker");
pub const BBPATH: &str = concatcp!(INTERNAL_DIR, "/busybox");
pub const DEVICEDIR: &str = concatcp!(INTERNAL_DIR, "/device"); pub const DEVICEDIR: &str = concatcp!(INTERNAL_DIR, "/device");
pub const PREINITDEV: &str = concatcp!(DEVICEDIR, "/preinit"); pub const PREINITDEV: &str = concatcp!(DEVICEDIR, "/preinit");
pub const LOG_PIPE: &str = concatcp!(DEVICEDIR, "/log"); pub const LOG_PIPE: &str = concatcp!(DEVICEDIR, "/log");