mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-07-29 21:03:50 +00:00
Refactor magisk bins injection logic
Magisk binary mounting logic is not very clear now. In this commit, it is rewritten in a more robust way. Now it has following cases in mind: 1) Device has a su binary, magisk need to overlay it 2) Choose the PATH with least files to reduce bind mount 3) Filter path which is not suitable
This commit is contained in:
parent
3a37e8c9c5
commit
7b2d40987c
@ -3,12 +3,15 @@ use crate::ffi::{ModuleInfo, get_magisk_tmp};
|
|||||||
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,
|
||||||
Utf8CString, clone_attr, cstr, debug, error, info, libc, warn,
|
Utf8CString, WalkResult, clone_attr, cstr, debug, error, info, libc, warn,
|
||||||
};
|
};
|
||||||
use libc::{MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
|
use libc::{MS_RDONLY, O_CLOEXEC, O_CREAT, O_RDONLY};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::{Component, Path};
|
use std::path::{Component, Path};
|
||||||
|
|
||||||
|
const MAGISK_BIN_INJECT_PARTITIONS: [&Utf8CStr; 4] =
|
||||||
|
[cstr!("/system/"), cstr!("/vendor/"), cstr!("/product/"), cstr!("/system_ext/")];
|
||||||
|
|
||||||
const SECONDARY_READ_ONLY_PARTITIONS: [&Utf8CStr; 3] =
|
const SECONDARY_READ_ONLY_PARTITIONS: [&Utf8CStr; 3] =
|
||||||
[cstr!("/vendor"), cstr!("/product"), cstr!("/system_ext")];
|
[cstr!("/vendor"), cstr!("/product"), cstr!("/system_ext")];
|
||||||
|
|
||||||
@ -370,31 +373,59 @@ fn inject_magisk_bins(system: &mut FsNode) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First find whether /system/bin exists
|
// Strip /system prefix to insert correct node
|
||||||
let bin = system.children().and_then(|c| c.get_mut("bin"));
|
fn strip_system_prefix(orig_item: &str) -> String {
|
||||||
if let Some(FsNode::Directory { children }) = bin {
|
match orig_item.strip_prefix("/system/") {
|
||||||
inject(children);
|
Some(rest) => format!("/{}", rest),
|
||||||
return;
|
None => orig_item.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If /system/bin node does not exist, use the first suitable directory in PATH
|
|
||||||
let path_env = get_path_env();
|
let path_env = get_path_env();
|
||||||
let bin_paths = path_env.split(':').filter_map(|path| {
|
let mut candidates = vec![];
|
||||||
if SECONDARY_READ_ONLY_PARTITIONS
|
|
||||||
.iter()
|
for orig_item in path_env.split(':') {
|
||||||
.any(|p| path.starts_with(p.as_str()))
|
// Filter not suitbale paths
|
||||||
{
|
if !MAGISK_BIN_INJECT_PARTITIONS.iter().any(|p| orig_item.starts_with(p.as_str())) {
|
||||||
let path = Utf8CString::from(path);
|
continue;
|
||||||
if let Ok(attr) = path.get_attr()
|
}
|
||||||
&& (attr.st.st_mode & 0x0001) != 0
|
// Flatten apex path is not suitable too
|
||||||
{
|
if orig_item.starts_with("/system/apex/") {
|
||||||
return Some(path);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override existing su first
|
||||||
|
let su_path = Utf8CString::from(format!("{}/su", orig_item));
|
||||||
|
if su_path.exists() {
|
||||||
|
let item = strip_system_prefix(orig_item);
|
||||||
|
candidates.push((item, 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = Utf8CString::from(orig_item);
|
||||||
|
if let Ok(attr) = path.get_attr() && (attr.st.st_mode & 0x0001) != 0 {
|
||||||
|
if let Ok(mut dir) = Directory::open(&path) {
|
||||||
|
let mut count = 0;
|
||||||
|
if let Err(_) = dir.pre_order_walk(|e| {
|
||||||
|
if e.is_file() {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
Ok(WalkResult::Continue)
|
||||||
|
}) {
|
||||||
|
// Skip, we cannot ensure the result is correct
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let item = strip_system_prefix(orig_item);
|
||||||
|
candidates.push((item, count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
}
|
||||||
});
|
|
||||||
'path_loop: for path in bin_paths {
|
// Sort by amount of files
|
||||||
let components = Path::new(&path)
|
candidates.sort_by_key(|&(_, count)| count);
|
||||||
|
|
||||||
|
'path_loop: for candidate in candidates {
|
||||||
|
let components = Path::new(&candidate.0)
|
||||||
.components()
|
.components()
|
||||||
.filter(|c| matches!(c, Component::Normal(_)))
|
.filter(|c| matches!(c, Component::Normal(_)))
|
||||||
.filter_map(|c| c.as_os_str().to_str());
|
.filter_map(|c| c.as_os_str().to_str());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user