mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-07-28 20:33:37 +00:00
Move Zygisk code out of module.cpp
This commit is contained in:
parent
2a42ca2b8f
commit
55c3ee3a6f
@ -218,13 +218,7 @@ static void handle_request_sync(int client, int code) {
|
|||||||
denylist_handler(-1, nullptr);
|
denylist_handler(-1, nullptr);
|
||||||
|
|
||||||
// Restore native bridge property
|
// Restore native bridge property
|
||||||
auto nb = get_prop(NBPROP);
|
restore_zygisk_prop();
|
||||||
auto len = sizeof(ZYGISKLDR) - 1;
|
|
||||||
if (nb == ZYGISKLDR) {
|
|
||||||
set_prop(NBPROP, "0");
|
|
||||||
} else if (nb.size() > len) {
|
|
||||||
set_prop(NBPROP, nb.data() + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_int(client, 0);
|
write_int(client, 0);
|
||||||
|
|
||||||
|
@ -145,8 +145,9 @@ impl MagiskD {
|
|||||||
);
|
);
|
||||||
initialize_denylist();
|
initialize_denylist();
|
||||||
setup_module_mount();
|
setup_module_mount();
|
||||||
let modules = self.handle_modules();
|
let modules = self.load_modules();
|
||||||
self.module_list.set(modules).ok();
|
self.module_list.set(modules).ok();
|
||||||
|
self.apply_modules();
|
||||||
clean_mounts();
|
clean_mounts();
|
||||||
|
|
||||||
false
|
false
|
||||||
|
@ -28,14 +28,16 @@ enum class RespondCode : int {
|
|||||||
|
|
||||||
struct ModuleInfo;
|
struct ModuleInfo;
|
||||||
|
|
||||||
extern std::string native_bridge;
|
|
||||||
|
|
||||||
// Daemon
|
// Daemon
|
||||||
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 setup_magisk_env();
|
||||||
bool check_key_combo();
|
bool check_key_combo();
|
||||||
|
|
||||||
|
// Zygisk daemon
|
||||||
|
rust::Str get_zygisk_lib_name();
|
||||||
|
void set_zygisk_prop();
|
||||||
void restore_zygisk_prop();
|
void restore_zygisk_prop();
|
||||||
|
|
||||||
// Sockets
|
// Sockets
|
||||||
|
@ -12,7 +12,6 @@ use cxx::{ExternType, type_id};
|
|||||||
use daemon::{MagiskD, daemon_entry};
|
use daemon::{MagiskD, daemon_entry};
|
||||||
use derive::Decodable;
|
use derive::Decodable;
|
||||||
use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging};
|
use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging};
|
||||||
use module::load_modules;
|
|
||||||
use mount::{find_preinit_device, revert_unmount};
|
use mount::{find_preinit_device, revert_unmount};
|
||||||
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
|
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
|
||||||
use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon};
|
use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon};
|
||||||
@ -173,6 +172,7 @@ pub mod ffi {
|
|||||||
fn uninstall_pkg(apk: Utf8CStrRef);
|
fn uninstall_pkg(apk: Utf8CStrRef);
|
||||||
fn update_deny_flags(uid: i32, process: &str, flags: &mut u32);
|
fn update_deny_flags(uid: i32, process: &str, flags: &mut u32);
|
||||||
fn initialize_denylist();
|
fn initialize_denylist();
|
||||||
|
fn get_zygisk_lib_name() -> &'static str;
|
||||||
fn restore_zygisk_prop();
|
fn restore_zygisk_prop();
|
||||||
fn switch_mnt_ns(pid: i32) -> i32;
|
fn switch_mnt_ns(pid: i32) -> i32;
|
||||||
fn app_request(req: &SuAppRequest) -> i32;
|
fn app_request(req: &SuAppRequest) -> i32;
|
||||||
@ -223,8 +223,6 @@ pub mod ffi {
|
|||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
fn daemon_entry();
|
fn daemon_entry();
|
||||||
#[namespace = "rust"]
|
|
||||||
fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default constructors
|
// Default constructors
|
||||||
@ -259,7 +257,7 @@ pub mod ffi {
|
|||||||
fn get() -> &'static MagiskD;
|
fn get() -> &'static MagiskD;
|
||||||
}
|
}
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
fn handle_modules(self: &MagiskD) -> Vec<ModuleInfo>;
|
fn load_modules(self: &MagiskD) -> Vec<ModuleInfo>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ static rust::Vec<ModuleInfo> collect_modules(bool zygisk_enabled, bool open_zygi
|
|||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
};
|
};
|
||||||
std::for_each(modules.begin(),modules.end(), [&](ModuleInfo &info) {
|
ranges::for_each(modules, [&](ModuleInfo &info) {
|
||||||
info.z32 = convert_to_memfd(info.z32);
|
info.z32 = convert_to_memfd(info.z32);
|
||||||
info.z64 = convert_to_memfd(info.z64);
|
info.z64 = convert_to_memfd(info.z64);
|
||||||
});
|
});
|
||||||
@ -133,28 +133,15 @@ static rust::Vec<ModuleInfo> collect_modules(bool zygisk_enabled, bool open_zygi
|
|||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
rust::Vec<ModuleInfo> MagiskD::handle_modules() const noexcept {
|
rust::Vec<ModuleInfo> MagiskD::load_modules() const noexcept {
|
||||||
bool zygisk = zygisk_enabled();
|
bool zygisk = zygisk_enabled();
|
||||||
prepare_modules();
|
prepare_modules();
|
||||||
exec_module_scripts("post-fs-data", collect_modules(zygisk, false));
|
exec_module_scripts("post-fs-data", collect_modules(zygisk, false));
|
||||||
// Recollect modules (module scripts could remove itself)
|
// Recollect modules (module scripts could remove itself)
|
||||||
auto list = collect_modules(zygisk, true);
|
auto list = collect_modules(zygisk, true);
|
||||||
|
|
||||||
if (zygisk) {
|
if (zygisk) {
|
||||||
string native_bridge_orig = get_prop(NBPROP);
|
set_zygisk_prop();
|
||||||
if (native_bridge_orig.empty()) {
|
|
||||||
native_bridge_orig = "0";
|
|
||||||
}
|
|
||||||
native_bridge = native_bridge_orig != "0" ? ZYGISKLDR + native_bridge_orig : ZYGISKLDR;
|
|
||||||
set_prop(NBPROP, native_bridge.data());
|
|
||||||
// Whether Huawei's Maple compiler is enabled.
|
|
||||||
// If so, system server will be created by a special Zygote which ignores the native bridge
|
|
||||||
// and make system server out of our control. Avoid it by disabling.
|
|
||||||
if (get_prop("ro.maple.enable") == "1") {
|
|
||||||
set_prop("ro.maple.enable", "0");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rust::load_modules(rust::Slice<const ModuleInfo>(list), zygisk ? native_bridge : "");
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::consts::{MODULEMNT, MODULEROOT, WORKERDIR};
|
use crate::consts::{MODULEMNT, MODULEROOT, WORKERDIR};
|
||||||
use crate::ffi::{ModuleInfo, get_magisk_tmp};
|
use crate::daemon::MagiskD;
|
||||||
|
use crate::ffi::{get_magisk_tmp, get_zygisk_lib_name};
|
||||||
use crate::load_prop_file;
|
use crate::load_prop_file;
|
||||||
use base::{
|
use base::{
|
||||||
Directory, FsPathBuilder, LoggedResult, OsResultStatic, ResultExt, Utf8CStr, Utf8CStrBuf,
|
Directory, FsPathBuilder, LoggedResult, OsResultStatic, ResultExt, Utf8CStr, Utf8CStrBuf,
|
||||||
@ -487,7 +488,9 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inject_zygisk_bins(system: &mut FsNode, name: &str) {
|
fn inject_zygisk_bins(system: &mut FsNode) {
|
||||||
|
let name = get_zygisk_lib_name();
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
let has_32_bit = cstr!("/system/bin/linker").exists();
|
let has_32_bit = cstr!("/system/bin/linker").exists();
|
||||||
|
|
||||||
@ -543,110 +546,112 @@ fn inject_zygisk_bins(system: &mut FsNode, name: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_modules(module_list: &[ModuleInfo], zygisk_name: &str) {
|
impl MagiskD {
|
||||||
let mut system = FsNode::new_dir();
|
pub fn apply_modules(&self) {
|
||||||
|
let mut system = FsNode::new_dir();
|
||||||
|
|
||||||
// Build all the base "prefix" paths
|
// Build all the base "prefix" paths
|
||||||
let mut root = cstr::buf::default().join_path("/");
|
let mut root = cstr::buf::default().join_path("/");
|
||||||
|
|
||||||
let mut module_dir = cstr::buf::default().join_path(MODULEROOT);
|
let mut module_dir = cstr::buf::default().join_path(MODULEROOT);
|
||||||
|
|
||||||
let mut module_mnt = cstr::buf::default()
|
let mut module_mnt = cstr::buf::default()
|
||||||
.join_path(get_magisk_tmp())
|
.join_path(get_magisk_tmp())
|
||||||
.join_path(MODULEMNT);
|
.join_path(MODULEMNT);
|
||||||
|
|
||||||
let mut worker = cstr::buf::default()
|
let mut worker = cstr::buf::default()
|
||||||
.join_path(get_magisk_tmp())
|
.join_path(get_magisk_tmp())
|
||||||
.join_path(WORKERDIR);
|
.join_path(WORKERDIR);
|
||||||
|
|
||||||
// Create a collection of all relevant paths
|
// Create a collection of all relevant paths
|
||||||
let mut root_paths = FilePaths {
|
let mut root_paths = FilePaths {
|
||||||
real: PathTracker::from(&mut root),
|
real: PathTracker::from(&mut root),
|
||||||
worker: PathTracker::from(&mut worker),
|
worker: PathTracker::from(&mut worker),
|
||||||
module_mnt: PathTracker::from(&mut module_mnt),
|
module_mnt: PathTracker::from(&mut module_mnt),
|
||||||
module_root: PathTracker::from(&mut module_dir),
|
module_root: PathTracker::from(&mut module_dir),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 1: Create virtual filesystem tree
|
// Step 1: Create virtual filesystem tree
|
||||||
//
|
//
|
||||||
// In this step, there is zero logic applied during tree construction; we simply collect
|
// In this step, there is zero logic applied during tree construction; we simply collect and
|
||||||
// and record the union of all module filesystem trees under each of their /system directory.
|
// record the union of all module filesystem trees under each of their /system directory.
|
||||||
|
|
||||||
for info in module_list {
|
for info in self.module_list.get().iter().flat_map(|v| v.iter()) {
|
||||||
let mut module_paths = root_paths.append(&info.name);
|
let mut module_paths = root_paths.append(&info.name);
|
||||||
{
|
|
||||||
// Read props
|
|
||||||
let prop = module_paths.append("system.prop");
|
|
||||||
if prop.module().exists() {
|
|
||||||
// Do NOT go through property service as it could cause boot lock
|
|
||||||
load_prop_file(prop.module(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Check whether skip mounting
|
|
||||||
let skip = module_paths.append("skip_mount");
|
|
||||||
if skip.module().exists() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Double check whether the system folder exists
|
|
||||||
let sys = module_paths.append("system");
|
|
||||||
if sys.module().exists() {
|
|
||||||
info!("{}: loading module files", &info.name);
|
|
||||||
system.collect(sys).log_ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: Inject custom files
|
|
||||||
//
|
|
||||||
// Magisk provides some built-in functionality that requires augmenting the filesystem.
|
|
||||||
// We expose several cmdline tools (e.g. su) into PATH, and the zygisk shared library
|
|
||||||
// has to also be added into the default LD_LIBRARY_PATH for code injection.
|
|
||||||
// We directly inject file nodes into the virtual filesystem tree we built in the previous
|
|
||||||
// step, treating Magisk just like a special "module".
|
|
||||||
|
|
||||||
if get_magisk_tmp() != "/sbin" || get_path_env().split(":").all(|s| s != "/sbin") {
|
|
||||||
inject_magisk_bins(&mut system);
|
|
||||||
}
|
|
||||||
if !zygisk_name.is_empty() {
|
|
||||||
inject_zygisk_bins(&mut system, zygisk_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Extract all supported read-only partition roots
|
|
||||||
//
|
|
||||||
// For simplicity and backwards compatibility on older Android versions, when constructing
|
|
||||||
// Magisk modules, we always assume that there is only a single read-only partition mounted
|
|
||||||
// at /system. However, on modern Android there are actually multiple read-only partitions
|
|
||||||
// mounted at their respective paths. We need to extract these subtrees out of the main
|
|
||||||
// tree and treat them as individual trees.
|
|
||||||
|
|
||||||
let mut roots = BTreeMap::new(); /* mapOf(partition_name -> FsNode) */
|
|
||||||
if let FsNode::Directory { children } = &mut system {
|
|
||||||
for dir in SECONDARY_READ_ONLY_PARTITIONS {
|
|
||||||
// Only treat these nodes as root iff it is actually a directory in rootdir
|
|
||||||
if let Ok(attr) = dir.get_attr()
|
|
||||||
&& attr.is_dir()
|
|
||||||
{
|
{
|
||||||
let name = dir.trim_start_matches('/');
|
// Read props
|
||||||
if let Some(root) = children.remove(name) {
|
let prop = module_paths.append("system.prop");
|
||||||
roots.insert(name, root);
|
if prop.module().exists() {
|
||||||
|
// Do NOT go through property service as it could cause boot lock
|
||||||
|
load_prop_file(prop.module(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Check whether skip mounting
|
||||||
|
let skip = module_paths.append("skip_mount");
|
||||||
|
if skip.module().exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Double check whether the system folder exists
|
||||||
|
let sys = module_paths.append("system");
|
||||||
|
if sys.module().exists() {
|
||||||
|
info!("{}: loading module files", &info.name);
|
||||||
|
system.collect(sys).log_ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
roots.insert("system", system);
|
|
||||||
|
|
||||||
for (dir, mut root) in roots {
|
// Step 2: Inject custom files
|
||||||
// Step 4: Convert virtual filesystem tree into concrete operations
|
|
||||||
//
|
//
|
||||||
// Compare the virtual filesystem tree we constructed against the real filesystem
|
// Magisk provides some built-in functionality that requires augmenting the filesystem.
|
||||||
// structure on-device to generate a series of "operations".
|
// We expose several cmdline tools (e.g. su) into PATH, and the zygisk shared library
|
||||||
// The "core" of the logic is to decide which directories need to be rebuilt in the
|
// has to also be added into the default LD_LIBRARY_PATH for code injection.
|
||||||
// tmpfs worker directory, and real sub-nodes need to be mirrored inside it.
|
// We directly inject file nodes into the virtual filesystem tree we built in the previous
|
||||||
|
// step, treating Magisk just like a special "module".
|
||||||
|
|
||||||
let path = root_paths.append(dir);
|
if get_magisk_tmp() != "/sbin" || get_path_env().split(":").all(|s| s != "/sbin") {
|
||||||
root.commit(path, true).log_ok();
|
inject_magisk_bins(&mut system);
|
||||||
|
}
|
||||||
|
if self.zygisk_enabled() {
|
||||||
|
inject_zygisk_bins(&mut system);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Extract all supported read-only partition roots
|
||||||
|
//
|
||||||
|
// For simplicity and backwards compatibility on older Android versions, when constructing
|
||||||
|
// Magisk modules, we always assume that there is only a single read-only partition mounted
|
||||||
|
// at /system. However, on modern Android there are actually multiple read-only partitions
|
||||||
|
// mounted at their respective paths. We need to extract these subtrees out of the main
|
||||||
|
// tree and treat them as individual trees.
|
||||||
|
|
||||||
|
let mut roots = BTreeMap::new(); /* mapOf(partition_name -> FsNode) */
|
||||||
|
if let FsNode::Directory { children } = &mut system {
|
||||||
|
for dir in SECONDARY_READ_ONLY_PARTITIONS {
|
||||||
|
// Only treat these nodes as root iff it is actually a directory in rootdir
|
||||||
|
if let Ok(attr) = dir.get_attr()
|
||||||
|
&& attr.is_dir()
|
||||||
|
{
|
||||||
|
let name = dir.trim_start_matches('/');
|
||||||
|
if let Some(root) = children.remove(name) {
|
||||||
|
roots.insert(name, root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roots.insert("system", system);
|
||||||
|
|
||||||
|
for (dir, mut root) in roots {
|
||||||
|
// Step 4: Convert virtual filesystem tree into concrete operations
|
||||||
|
//
|
||||||
|
// Compare the virtual filesystem tree we constructed against the real filesystem
|
||||||
|
// structure on-device to generate a series of "operations".
|
||||||
|
// The "core" of the logic is to decide which directories need to be rebuilt in the
|
||||||
|
// tmpfs worker directory, and real sub-nodes need to be mirrored inside it.
|
||||||
|
|
||||||
|
let path = root_paths.append(dir);
|
||||||
|
root.commit(path, true).log_ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
string native_bridge = "0";
|
static string zygisk_lib_name = "0";
|
||||||
|
|
||||||
static void zygiskd(int socket) {
|
static void zygiskd(int socket) {
|
||||||
if (getuid() != 0 || fcntl(socket, F_GETFD) < 0)
|
if (getuid() != 0 || fcntl(socket, F_GETFD) < 0)
|
||||||
@ -110,10 +110,29 @@ extern "C" [[maybe_unused]] NativeBridgeCallbacks NativeBridgeItf {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rust::Str get_zygisk_lib_name() {
|
||||||
|
return zygisk_lib_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_zygisk_prop() {
|
||||||
|
string native_bridge_orig = get_prop(NBPROP);
|
||||||
|
if (native_bridge_orig.empty()) {
|
||||||
|
native_bridge_orig = "0";
|
||||||
|
}
|
||||||
|
zygisk_lib_name = native_bridge_orig == "0" ? ZYGISKLDR : ZYGISKLDR + native_bridge_orig;
|
||||||
|
set_prop(NBPROP, zygisk_lib_name.data());
|
||||||
|
// Whether Huawei's Maple compiler is enabled.
|
||||||
|
// If so, system server will be created by a special Zygote which ignores the native bridge
|
||||||
|
// and make system server out of our control. Avoid it by disabling.
|
||||||
|
if (get_prop("ro.maple.enable") == "1") {
|
||||||
|
set_prop("ro.maple.enable", "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void restore_zygisk_prop() {
|
void restore_zygisk_prop() {
|
||||||
string native_bridge_orig = "0";
|
string native_bridge_orig = "0";
|
||||||
if (native_bridge.length() > strlen(ZYGISKLDR)) {
|
if (zygisk_lib_name.length() > strlen(ZYGISKLDR)) {
|
||||||
native_bridge_orig = native_bridge.substr(strlen(ZYGISKLDR));
|
native_bridge_orig = zygisk_lib_name.substr(strlen(ZYGISKLDR));
|
||||||
}
|
}
|
||||||
set_prop(NBPROP, native_bridge_orig.data());
|
set_prop(NBPROP, native_bridge_orig.data());
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <core.hpp>
|
#include <core.hpp>
|
||||||
|
|
||||||
|
#define ZYGISKLDR "libzygisk.so"
|
||||||
|
#define NBPROP "ro.dalvik.vm.native.bridge"
|
||||||
|
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
#define ZLOGD(...) LOGD("zygisk64: " __VA_ARGS__)
|
#define ZLOGD(...) LOGD("zygisk64: " __VA_ARGS__)
|
||||||
#define ZLOGE(...) LOGE("zygisk64: " __VA_ARGS__)
|
#define ZLOGE(...) LOGE("zygisk64: " __VA_ARGS__)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
||||||
#define ZYGISKLDR "libzygisk.so"
|
|
||||||
#define NBPROP "ro.dalvik.vm.native.bridge"
|
|
||||||
#define SECURE_DIR "/data/adb"
|
#define SECURE_DIR "/data/adb"
|
||||||
#define MODULEROOT SECURE_DIR "/modules"
|
#define MODULEROOT SECURE_DIR "/modules"
|
||||||
#define MODULEUPGRADE SECURE_DIR "/modules_update"
|
#define MODULEUPGRADE SECURE_DIR "/modules_update"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user