mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-11 10:37:33 +00:00
Migrate disable/remove modules to Rust
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
use crate::consts::{MAGISK_FULL_VER, MAGISK_PROC_CON, MAIN_CONFIG, ROOTMNT, ROOTOVL, SECURE_DIR};
|
||||
use crate::db::Sqlite3;
|
||||
use crate::ffi::{
|
||||
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, disable_modules, exec_common_scripts,
|
||||
exec_module_scripts, get_magisk_tmp, initialize_denylist, setup_magisk_env,
|
||||
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, exec_common_scripts, exec_module_scripts,
|
||||
get_magisk_tmp, get_prop, initialize_denylist, set_prop, setup_magisk_env,
|
||||
};
|
||||
use crate::logging::{magisk_logging, setup_logfile, start_log_daemon};
|
||||
use crate::module::disable_modules;
|
||||
use crate::mount::{clean_mounts, setup_preinit_dir};
|
||||
use crate::package::ManagerInfo;
|
||||
use crate::selinux::restore_tmpcon;
|
||||
use crate::su::SuInfo;
|
||||
use crate::{get_prop, set_prop};
|
||||
use base::libc::{O_APPEND, O_CLOEXEC, O_RDONLY, O_WRONLY};
|
||||
use base::{
|
||||
AtomicArc, BufReadExt, FsPathBuilder, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, error, info, libc,
|
||||
|
@@ -92,10 +92,6 @@ void exec_task(std::function<void()> &&task);
|
||||
// Daemon handlers
|
||||
void denylist_handler(int client, const sock_cred *cred);
|
||||
|
||||
// Module stuffs
|
||||
void disable_modules();
|
||||
void remove_modules();
|
||||
|
||||
// Scripting
|
||||
void install_apk(rust::Utf8CStr apk);
|
||||
void uninstall_pkg(rust::Utf8CStr pkg);
|
||||
@@ -125,3 +121,4 @@ static inline rust::Utf8CStr get_magisk_tmp_rs() { return get_magisk_tmp(); }
|
||||
static inline rust::String resolve_preinit_dir_rs(rust::Utf8CStr base_dir) {
|
||||
return resolve_preinit_dir(base_dir.c_str());
|
||||
}
|
||||
static inline void exec_script_rs(rust::Utf8CStr script) { exec_script(script.data()); }
|
||||
|
@@ -20,12 +20,19 @@ private:
|
||||
};
|
||||
|
||||
// System properties
|
||||
rust::String get_prop_rs(const char *name, bool persist);
|
||||
std::string get_prop(const char *name, bool persist = false);
|
||||
int delete_prop(const char *name, bool persist = false);
|
||||
int set_prop(const char *name, const char *value, bool skip_svc = false);
|
||||
void load_prop_file(const char *filename, bool skip_svc = false);
|
||||
|
||||
static inline void prop_cb_exec(prop_cb &cb, const char *name, const char *value, uint32_t serial) {
|
||||
cb.exec(name, value, serial);
|
||||
// Rust bindings
|
||||
rust::String get_prop_rs(rust::Utf8CStr name, bool persist);
|
||||
static inline int set_prop_rs(rust::Utf8CStr name, rust::Utf8CStr value, bool skip_svc) {
|
||||
return set_prop(name.data(), value.data(), skip_svc);
|
||||
}
|
||||
static inline void load_prop_file_rs(rust::Utf8CStr filename, bool skip_svc) {
|
||||
load_prop_file(filename.data(), skip_svc);
|
||||
}
|
||||
static inline void prop_cb_exec(prop_cb &cb, rust::Utf8CStr name, rust::Utf8CStr value, uint32_t serial) {
|
||||
cb.exec(name.data(), value.data(), serial);
|
||||
}
|
@@ -7,11 +7,12 @@
|
||||
|
||||
use crate::ffi::SuRequest;
|
||||
use crate::socket::Encodable;
|
||||
use base::{Utf8CStr, libc};
|
||||
use base::libc;
|
||||
use cxx::{ExternType, type_id};
|
||||
use daemon::{MagiskD, daemon_entry};
|
||||
use derive::Decodable;
|
||||
use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging};
|
||||
use module::remove_modules;
|
||||
use mount::{find_preinit_device, revert_unmount};
|
||||
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
|
||||
use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon};
|
||||
@@ -133,23 +134,6 @@ pub mod ffi {
|
||||
request: &'a SuRequest,
|
||||
}
|
||||
|
||||
extern "C++" {
|
||||
include!("include/resetprop.hpp");
|
||||
|
||||
#[cxx_name = "prop_cb"]
|
||||
type PropCb;
|
||||
unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String;
|
||||
#[cxx_name = "set_prop"]
|
||||
unsafe fn set_prop_rs(name: *const c_char, value: *const c_char, skip_svc: bool) -> i32;
|
||||
unsafe fn prop_cb_exec(
|
||||
cb: Pin<&mut PropCb>,
|
||||
name: *const c_char,
|
||||
value: *const c_char,
|
||||
serial: u32,
|
||||
);
|
||||
unsafe fn load_prop_file(filename: *const c_char, skip_svc: bool);
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
#[namespace = "rust"]
|
||||
#[cxx_name = "Utf8CStr"]
|
||||
@@ -165,7 +149,8 @@ pub mod ffi {
|
||||
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
|
||||
fn setup_magisk_env() -> bool;
|
||||
fn check_key_combo() -> bool;
|
||||
fn disable_modules();
|
||||
#[cxx_name = "exec_script_rs"]
|
||||
fn exec_script(script: Utf8CStrRef);
|
||||
fn exec_common_scripts(stage: Utf8CStrRef);
|
||||
fn exec_module_scripts(state: Utf8CStrRef, modules: &Vec<ModuleInfo>);
|
||||
fn install_apk(apk: Utf8CStrRef);
|
||||
@@ -193,6 +178,18 @@ pub mod ffi {
|
||||
fn get_text(self: &DbValues, index: i32) -> &str;
|
||||
fn bind_text(self: Pin<&mut DbStatement>, index: i32, val: &str) -> i32;
|
||||
fn bind_int64(self: Pin<&mut DbStatement>, index: i32, val: i64) -> i32;
|
||||
|
||||
include!("include/resetprop.hpp");
|
||||
|
||||
#[cxx_name = "prop_cb"]
|
||||
type PropCb;
|
||||
#[cxx_name = "get_prop_rs"]
|
||||
fn get_prop(name: Utf8CStrRef, persist: bool) -> String;
|
||||
#[cxx_name = "set_prop_rs"]
|
||||
fn set_prop(name: Utf8CStrRef, value: Utf8CStrRef, skip_svc: bool) -> i32;
|
||||
#[cxx_name = "load_prop_file_rs"]
|
||||
fn load_prop_file(filename: Utf8CStrRef, skip_svc: bool);
|
||||
fn prop_cb_exec(cb: Pin<&mut PropCb>, name: Utf8CStrRef, value: Utf8CStrRef, serial: u32);
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
@@ -203,6 +200,7 @@ pub mod ffi {
|
||||
fn setup_logfile();
|
||||
fn find_preinit_device() -> String;
|
||||
fn revert_unmount(pid: i32);
|
||||
fn remove_modules();
|
||||
fn zygisk_should_load_module(flags: u32) -> bool;
|
||||
unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>);
|
||||
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
||||
@@ -277,15 +275,3 @@ impl SuRequest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_prop(name: &Utf8CStr, persist: bool) -> String {
|
||||
unsafe { ffi::get_prop_rs(name.as_ptr(), persist) }
|
||||
}
|
||||
|
||||
pub fn set_prop(name: &Utf8CStr, value: &Utf8CStr, skip_svc: bool) -> bool {
|
||||
unsafe { ffi::set_prop_rs(name.as_ptr(), value.as_ptr(), skip_svc) == 0 }
|
||||
}
|
||||
|
||||
pub fn load_prop_file(filename: &Utf8CStr, skip_svc: bool) {
|
||||
unsafe { ffi::load_prop_file(filename.as_ptr(), skip_svc) };
|
||||
}
|
||||
|
@@ -117,41 +117,3 @@ rust::Vec<ModuleInfo> MagiskD::load_modules() const noexcept {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static int check_rules_dir(char *buf, size_t sz) {
|
||||
int off = ssprintf(buf, sz, "%s/" PREINITMIRR, get_magisk_tmp());
|
||||
struct stat st1{};
|
||||
struct stat st2{};
|
||||
if (xstat(buf, &st1) < 0 || xstat(MODULEROOT, &st2) < 0)
|
||||
return 0;
|
||||
if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
|
||||
return 0;
|
||||
return off;
|
||||
}
|
||||
|
||||
void disable_modules() {
|
||||
char buf[4096];
|
||||
int off = check_rules_dir(buf, sizeof(buf));
|
||||
foreach_module([&](int, dirent *entry, int modfd) {
|
||||
close(xopenat(modfd, "disable", O_RDONLY | O_CREAT | O_CLOEXEC, 0));
|
||||
if (off) {
|
||||
ssprintf(buf + off, sizeof(buf) - off, "/%s/sepolicy.rule", entry->d_name);
|
||||
unlink(buf);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void remove_modules() {
|
||||
char buf[4096];
|
||||
int off = check_rules_dir(buf, sizeof(buf));
|
||||
foreach_module([&](int, dirent *entry, int) {
|
||||
auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh";
|
||||
if (access(uninstaller.data(), F_OK) == 0)
|
||||
exec_script(uninstaller.data());
|
||||
if (off) {
|
||||
ssprintf(buf + off, sizeof(buf) - off, "/%s/sepolicy.rule", entry->d_name);
|
||||
unlink(buf);
|
||||
}
|
||||
});
|
||||
rm_rf(MODULEROOT);
|
||||
}
|
||||
|
@@ -1,11 +1,11 @@
|
||||
use crate::consts::{MODULEMNT, MODULEROOT, MODULEUPGRADE, WORKERDIR};
|
||||
use crate::daemon::MagiskD;
|
||||
use crate::ffi::{ModuleInfo, get_magisk_tmp, get_zygisk_lib_name};
|
||||
use crate::load_prop_file;
|
||||
use crate::ffi::{ModuleInfo, exec_script, get_magisk_tmp, get_zygisk_lib_name, load_prop_file};
|
||||
use crate::mount::setup_module_mount;
|
||||
use base::{
|
||||
Directory, FsPathBuilder, LibcReturn, LoggedResult, OsResultStatic, ResultExt, Utf8CStr,
|
||||
Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, warn,
|
||||
DirEntry, Directory, FsPathBuilder, LibcReturn, LoggedResult, OsResultStatic, ResultExt,
|
||||
Utf8CStr, Utf8CStrBuf, Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc,
|
||||
warn,
|
||||
};
|
||||
use libc::{AT_REMOVEDIR, MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
|
||||
use std::collections::BTreeMap;
|
||||
@@ -550,48 +550,7 @@ 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 {
|
||||
fn apply_modules(&self, module_list: &[ModuleInfo]) {
|
||||
fn apply_modules(zygisk: bool, module_list: &[ModuleInfo]) {
|
||||
let mut system = FsNode::new_dir();
|
||||
|
||||
// Build all the base "prefix" paths
|
||||
@@ -658,7 +617,7 @@ impl MagiskD {
|
||||
if get_magisk_tmp() != "/sbin" || get_path_env().split(":").all(|s| s != "/sbin") {
|
||||
inject_magisk_bins(&mut system);
|
||||
}
|
||||
if self.zygisk_enabled() {
|
||||
if zygisk {
|
||||
inject_zygisk_bins(&mut system);
|
||||
}
|
||||
|
||||
@@ -699,11 +658,87 @@ impl MagiskD {
|
||||
}
|
||||
}
|
||||
|
||||
fn upgrade_modules() -> LoggedResult<()> {
|
||||
let mut upgrade = Directory::open(cstr!(MODULEUPGRADE))?;
|
||||
let ufd = upgrade.as_raw_fd();
|
||||
let root = Directory::open(cstr!(MODULEROOT))?;
|
||||
while let Some(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(())
|
||||
}
|
||||
|
||||
fn for_each_module(func: impl Fn(&DirEntry) -> LoggedResult<()>) -> LoggedResult<()> {
|
||||
let mut root = Directory::open(cstr!(MODULEROOT))?;
|
||||
while let Some(ref e) = root.read()? {
|
||||
if e.is_dir() && e.name() != ".core" {
|
||||
func(e)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable_modules() {
|
||||
for_each_module(|e| {
|
||||
let dir = e.open_as_dir()?;
|
||||
dir.open_as_file_at(cstr!("disable"), O_RDONLY | O_CREAT | O_CLOEXEC, 0)?;
|
||||
Ok(())
|
||||
})
|
||||
.log_ok();
|
||||
}
|
||||
|
||||
pub fn remove_modules() {
|
||||
for_each_module(|e| {
|
||||
let dir = e.open_as_dir()?;
|
||||
if dir.contains_path(cstr!("uninstall.sh")) {
|
||||
let script = cstr::buf::default()
|
||||
.join_path(MODULEROOT)
|
||||
.join_path(e.name())
|
||||
.join_path("uninstall.sh");
|
||||
exec_script(&script);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.log_ok();
|
||||
cstr!(MODULEROOT).remove_all().log_ok();
|
||||
}
|
||||
|
||||
impl MagiskD {
|
||||
pub fn handle_modules(&self) {
|
||||
setup_module_mount();
|
||||
prepare_modules().ok();
|
||||
upgrade_modules().ok();
|
||||
let modules = self.load_modules();
|
||||
self.apply_modules(&modules);
|
||||
apply_modules(self.zygisk_enabled(), &modules);
|
||||
self.module_list.set(modules).ok();
|
||||
}
|
||||
}
|
||||
|
@@ -12,8 +12,7 @@ use base::{
|
||||
};
|
||||
|
||||
use crate::consts::{MODULEMNT, MODULEROOT, PREINITDEV, PREINITMIRR, WORKERDIR};
|
||||
use crate::ffi::{get_magisk_tmp, resolve_preinit_dir, switch_mnt_ns};
|
||||
use crate::get_prop;
|
||||
use crate::ffi::{get_magisk_tmp, get_prop, resolve_preinit_dir, switch_mnt_ns};
|
||||
|
||||
pub fn setup_preinit_dir() {
|
||||
let magisk_tmp = get_magisk_tmp();
|
||||
|
@@ -29,7 +29,7 @@ trait PropCbExec {
|
||||
|
||||
impl PropCbExec for Pin<&mut PropCb> {
|
||||
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) {
|
||||
unsafe { prop_cb_exec(self.as_mut(), name.as_ptr(), value.as_ptr(), u32::MAX) }
|
||||
prop_cb_exec(self.as_mut(), name, value, u32::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -429,8 +429,8 @@ static StringType get_prop_impl(const char *name, bool persist) {
|
||||
return get_prop<StringType>(name, flags);
|
||||
}
|
||||
|
||||
rust::String get_prop_rs(const char *name, bool persist) {
|
||||
return get_prop_impl<rust::String>(name, persist);
|
||||
rust::String get_prop_rs(rust::Utf8CStr name, bool persist) {
|
||||
return get_prop_impl<rust::String>(name.data(), persist);
|
||||
}
|
||||
|
||||
string get_prop(const char *name, bool persist) {
|
||||
|
Reference in New Issue
Block a user