diff --git a/native/src/base/files.rs b/native/src/base/files.rs index 358aed1cf..fcc2891f3 100644 --- a/native/src/base/files.rs +++ b/native/src/base/files.rs @@ -18,7 +18,6 @@ use std::fmt::Display; use std::fs::File; use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write}; use std::mem::MaybeUninit; -use std::ops::Deref; use std::os::fd::{AsFd, BorrowedFd}; use std::os::unix::ffi::OsStrExt; 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, ()> { if !attr.is_symlink() - && let Err(e) = nix::sys::stat::fchmodat( - AT_FDCWD, - self, - Mode::from_bits_truncate((attr.st.st_mode & 0o777).as_()), - FchmodatFlags::FollowSymlink, - ) + && let Err(e) = self.follow_link().chmod((attr.st.st_mode & 0o777).as_()) { // Double check if self is symlink before reporting error let self_attr = self.get_attr()?; 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 { 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> { #[allow(unused_mut)] 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")] con: cstr::buf::new(), }; @@ -537,16 +545,10 @@ impl FsPathFollow { } pub fn set_attr<'a>(&'a self, attr: &'a FileAttr) -> OsResult<'a, ()> { - nix::sys::stat::fchmodat( - AT_FDCWD, - self.deref(), - Mode::from_bits_truncate((attr.st.st_mode & 0o777).as_()), - FchmodatFlags::FollowSymlink, - ) - .check_os_err("chmod", Some(self), None)?; + self.chmod((attr.st.st_mode & 0o777).as_())?; nix::unistd::chown( - self.deref(), + self.as_utf8_cstr(), Some(Uid::from(attr.st.st_uid)), Some(Gid::from(attr.st.st_gid)), ) diff --git a/native/src/core/daemon.cpp b/native/src/core/daemon.cpp index 5cd9369ab..1c65d928b 100644 --- a/native/src/core/daemon.cpp +++ b/native/src/core/daemon.cpp @@ -214,53 +214,6 @@ int connect_daemon(int req, bool create) { 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() { int fd, dev, OFF = 0; diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 931449c26..47b71373c 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -1,19 +1,19 @@ use crate::UCred; use crate::consts::{ - MAGISK_FULL_VER, MAGISK_PROC_CON, MAGISK_VER_CODE, MAGISK_VERSION, MAIN_CONFIG, ROOTMNT, - ROOTOVL, SECURE_DIR, + APP_PACKAGE_NAME, BBPATH, DATABIN, MAGISK_FULL_VER, MAGISK_PROC_CON, MAGISK_VER_CODE, + MAGISK_VERSION, MAIN_CONFIG, MODULEROOT, ROOTMNT, ROOTOVL, SECURE_DIR, }; use crate::db::Sqlite3; use crate::ffi::{ 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::module::{disable_modules, remove_modules}; use crate::mount::{clean_mounts, setup_preinit_dir}; use crate::package::ManagerInfo; use crate::resetprop::{get_prop, set_prop}; -use crate::selinux::restore_tmpcon; +use crate::selinux::{restore_tmpcon, restorecon}; use crate::socket::IpcWrite; use crate::su::SuInfo; use crate::zygisk::ZygiskState; @@ -32,7 +32,7 @@ use std::fmt::Write as FmtWrite; use std::fs::File; use std::io::{BufReader, Write}; 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::{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 { setup_logfile(); info!("** post-fs-data mode running"); @@ -125,7 +202,7 @@ impl MagiskD { self.prune_su_access(); - if !setup_magisk_env() { + if !self.setup_magisk_env() { error!("* Magisk environment incomplete, abort"); return true; } diff --git a/native/src/core/include/core.hpp b/native/src/core/include/core.hpp index 93b923066..0c6b432c8 100644 --- a/native/src/core/include/core.hpp +++ b/native/src/core/include/core.hpp @@ -37,7 +37,6 @@ struct ModuleInfo; int connect_daemon(int req, bool create = false); const char *get_magisk_tmp(); void unlock_blocks(); -bool setup_magisk_env(); bool check_key_combo(); template requires(std::is_trivially_copyable_v) diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index eaf63faeb..34c9f81d9 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -137,7 +137,6 @@ pub mod ffi { fn get_magisk_tmp() -> Utf8CStrRef<'static>; #[cxx_name = "resolve_preinit_dir_rs"] fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String; - fn setup_magisk_env() -> bool; fn check_key_combo() -> bool; #[cxx_name = "exec_script_rs"] fn exec_script(script: Utf8CStrRef); diff --git a/native/src/include/consts.rs b/native/src/include/consts.rs index dec2f5cb5..0824eacd9 100644 --- a/native/src/include/consts.rs +++ b/native/src/include/consts.rs @@ -25,6 +25,7 @@ pub const MAIN_CONFIG: &str = concatcp!(INTERNAL_DIR, "/config"); pub const PREINITMIRR: &str = concatcp!(INTERNAL_DIR, "/preinit"); pub const MODULEMNT: &str = concatcp!(INTERNAL_DIR, "/modules"); 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 PREINITDEV: &str = concatcp!(DEVICEDIR, "/preinit"); pub const LOG_PIPE: &str = concatcp!(DEVICEDIR, "/log");