Refactor to better support Magisk

This commit is contained in:
Nullptr
2023-02-28 17:29:26 +08:00
parent 09b6673ab0
commit f465cbf810
11 changed files with 58 additions and 46 deletions

View File

@@ -36,7 +36,7 @@ val verCode by extra(gitCommitCount)
val minKsuVersion by extra(10654) val minKsuVersion by extra(10654)
val minKsudVersion by extra(10647) val minKsudVersion by extra(10647)
val maxKsuVersion by extra(20000) val maxKsuVersion by extra(20000)
val minMagiskVersion by extra(25000) val minMagiskVersion by extra(25208)
val androidMinSdkVersion by extra(29) val androidMinSdkVersion by extra(29)
val androidTargetSdkVersion by extra(33) val androidTargetSdkVersion by extra(33)

View File

@@ -70,13 +70,13 @@ void Constructor() {
LOGI("Load original native bridge: %s", native_bridge.data()); LOGI("Load original native bridge: %s", native_bridge.data());
sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW); sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW);
if (sOriginalBridge == nullptr) { if (sOriginalBridge == nullptr) {
LOGE("dlopen failed: %s", dlerror()); LOGE("%s", dlerror());
break; break;
} }
auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf"); auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf");
if (original_native_bridge_itf == nullptr) { if (original_native_bridge_itf == nullptr) {
LOGE("dlsym failed: %s", dlerror()); LOGE("%s", dlerror());
break; break;
} }

View File

@@ -38,7 +38,7 @@ androidComponents.onVariants { variant ->
into(moduleDir) into(moduleDir)
from("${rootProject.projectDir}/README.md") from("${rootProject.projectDir}/README.md")
from("$projectDir/src") { from("$projectDir/src") {
exclude("module.prop", "customize.sh", "daemon.sh") exclude("module.prop", "customize.sh", "service.sh")
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf")) filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
} }
from("$projectDir/src") { from("$projectDir/src") {
@@ -51,7 +51,7 @@ androidComponents.onVariants { variant ->
) )
} }
from("$projectDir/src") { from("$projectDir/src") {
include("customize.sh", "daemon.sh") include("customize.sh", "service.sh")
val tokens = mapOf( val tokens = mapOf(
"DEBUG" to if (buildTypeLowered == "debug") "true" else "false", "DEBUG" to if (buildTypeLowered == "debug") "true" else "false",
"MIN_KSU_VERSION" to "$minKsuVersion", "MIN_KSU_VERSION" to "$minKsuVersion",

View File

@@ -91,7 +91,6 @@ if [ "$KSU" ]; then
fi fi
ui_print "- Extracting module files" ui_print "- Extracting module files"
extract "$ZIPFILE" 'daemon.sh' "$MODPATH"
extract "$ZIPFILE" 'module.prop' "$MODPATH" extract "$ZIPFILE" 'module.prop' "$MODPATH"
extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH" extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH"
extract "$ZIPFILE" 'sepolicy.rule' "$MODPATH" extract "$ZIPFILE" 'sepolicy.rule' "$MODPATH"

View File

@@ -1,11 +0,0 @@
#!/system/bin/sh
DEBUG=@DEBUG@
# shellcheck disable=SC2155
export NATIVE_BRIDGE=$(getprop ro.dalvik.vm.native.bridge)
[ "$DEBUG" = true ] && export RUST_BACKTRACE=1
log -p i -t "zygisksu" "Start watchdog"
resetprop ro.dalvik.vm.native.bridge libzygiskloader.so
exec "bin/zygiskwd" "watchdog" >/dev/null 2>&1

View File

@@ -6,7 +6,8 @@ if [ "$ZYGISK_ENABLED" ]; then
fi fi
cd "$MODDIR" cd "$MODDIR"
export NATIVE_BRIDGE=$(getprop ro.dalvik.vm.native.bridge) getprop ro.dalvik.vm.native.bridge > /dev/.native_bridge
resetprop ro.dalvik.vm.native.bridge libzygiskloader.so
if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then
for file in ../*; do for file in ../*; do
@@ -20,5 +21,3 @@ if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then
fi fi
done done
fi fi
sh -c "./daemon.sh $@&"

View File

@@ -1,11 +1,15 @@
#!/system/bin/sh #!/system/bin/sh
DEBUG=@DEBUG@
MODDIR=${0%/*} MODDIR=${0%/*}
if [ "$ZYGISK_ENABLED" ]; then if [ "$ZYGISK_ENABLED" ]; then
exit 0 exit 0
fi fi
cd "$MODDIR" cd "$MODDIR"
export NATIVE_BRIDGE=$(cat /dev/.native_bridge)
rm /dev/.native_bridge
if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then
for file in ../*; do for file in ../*; do
@@ -19,3 +23,7 @@ if [ "$(which magisk)" ] && [ ".." -ef "/data/adb/modules" ]; then
fi fi
done done
fi fi
log -p i -t "zygisksu" "Start watchdog"
[ "$DEBUG" = true ] && export RUST_BACKTRACE=1
exec "bin/zygiskwd" "watchdog" >/dev/null 2>&1

View File

@@ -76,7 +76,7 @@ pub unsafe fn dlopen(path: &str, flags: i32) -> Result<*mut c_void> {
let result = android_dlopen_ext(filename, flags, &info); let result = android_dlopen_ext(filename, flags, &info);
if result.is_null() { if result.is_null() {
let e = std::ffi::CStr::from_ptr(libc::dlerror()).to_string_lossy(); let e = std::ffi::CStr::from_ptr(libc::dlerror()).to_string_lossy();
bail!("dlopen failed: {}", e); bail!(e);
} }
Ok(result) Ok(result)
} }

View File

@@ -1,6 +1,7 @@
use anyhow::Result; use anyhow::Result;
use nix::unistd::gettid; use nix::unistd::gettid;
use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command}; use std::{fs, io::{Read, Write}, os::unix::net::UnixStream, process::Command};
use std::ffi::c_char;
use std::os::fd::FromRawFd; use std::os::fd::FromRawFd;
use std::os::unix::net::UnixListener; use std::os::unix::net::UnixListener;
use nix::sys::socket::{AddressFamily, SockFlag, SockType, UnixAddr}; use nix::sys::socket::{AddressFamily, SockFlag, SockType, UnixAddr};
@@ -37,6 +38,24 @@ pub fn get_native_bridge() -> String {
std::env::var("NATIVE_BRIDGE").unwrap_or_default() std::env::var("NATIVE_BRIDGE").unwrap_or_default()
} }
pub fn log_raw(level: i32, tag: &str, message: &str) -> Result<()> {
let tag = std::ffi::CString::new(tag)?;
let message = std::ffi::CString::new(message)?;
unsafe {
__android_log_print(level as i32, tag.as_ptr(), message.as_ptr());
}
Ok(())
}
pub fn get_property(name: &str) -> Result<String> {
let name = std::ffi::CString::new(name)?;
let mut buf = vec![0u8; 92];
unsafe {
__system_property_get(name.as_ptr(), buf.as_mut_ptr() as *mut c_char);
}
Ok(String::from_utf8(buf)?)
}
pub fn set_property(name: &str, value: &str) -> Result<()> { pub fn set_property(name: &str, value: &str) -> Result<()> {
Command::new("resetprop") Command::new("resetprop")
.arg(name) .arg(name)
@@ -113,3 +132,8 @@ pub fn abstract_namespace_socket(name: &str) -> Result<UnixListener> {
let listener = unsafe { UnixListener::from_raw_fd(socket) }; let listener = unsafe { UnixListener::from_raw_fd(socket) };
Ok(listener) Ok(listener)
} }
extern "C" {
fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32;
fn __system_property_get(name: *const c_char, value: *mut c_char) -> u32;
}

View File

@@ -25,7 +25,7 @@ pub fn entry() -> Result<()> {
if check_and_set_hint()? == false { if check_and_set_hint()? == false {
log::warn!("Requirements not met, exiting"); log::warn!("Requirements not met, exiting");
utils::set_property(constants::PROP_NATIVE_BRIDGE, &utils::get_native_bridge())?; utils::set_property(constants::PROP_NATIVE_BRIDGE, &utils::get_native_bridge())?;
return Ok(()) return Ok(());
} }
let end = spawn_daemon(); let end = spawn_daemon();
set_prop_hint(constants::STATUS_CRASHED)?; set_prop_hint(constants::STATUS_CRASHED)?;
@@ -64,10 +64,21 @@ fn ensure_single_instance() -> Result<()> {
} }
fn mount_prop() -> Result<()> { fn mount_prop() -> Result<()> {
let module_prop = fs::File::open(constants::PATH_MODULE_PROP)?; let module_prop = if let root_impl::RootImpl::Magisk = root_impl::get_impl() {
let magisk_path = Command::new("magisk").arg("--path").output()?;
let mut magisk_path = String::from_utf8(magisk_path.stdout)?;
magisk_path.pop(); // Removing '\n'
let cwd = std::env::current_dir()?;
let dir = cwd.file_name().unwrap().to_string_lossy();
format!("{magisk_path}/.magisk/modules/{dir}/{}", constants::PATH_MODULE_PROP)
} else {
constants::PATH_MODULE_PROP.to_string()
};
log::info!("Mount {module_prop}");
let module_prop_file = fs::File::open(&module_prop)?;
let mut section = 0; let mut section = 0;
let mut sections: [String; 2] = [String::new(), String::new()]; let mut sections: [String; 2] = [String::new(), String::new()];
let lines = io::BufReader::new(module_prop).lines(); let lines = io::BufReader::new(module_prop_file).lines();
for line in lines { for line in lines {
let line = line?; let line = line?;
if line.starts_with("description=") { if line.starts_with("description=") {
@@ -83,21 +94,13 @@ fn mount_prop() -> Result<()> {
let _ = PROP_SECTIONS.set(sections); let _ = PROP_SECTIONS.set(sections);
fs::create_dir(constants::PATH_TMP_DIR)?; fs::create_dir(constants::PATH_TMP_DIR)?;
fs::File::create(constants::PATH_TMP_PROP)?;
// FIXME: sys_mount cannot be compiled on 32 bit // FIXME: sys_mount cannot be compiled on 32 bit
unsafe { unsafe {
let r = libc::mount(
CString::new("tmpfs")?.as_ptr(),
CString::new(constants::PATH_TMP_DIR)?.as_ptr(),
CString::new("tmpfs")?.as_ptr(),
0,
CString::new("mode=755")?.as_ptr() as *const libc::c_void,
);
Errno::result(r)?;
let _file = fs::File::create(constants::PATH_TMP_PROP)?;
let r = libc::mount( let r = libc::mount(
CString::new(constants::PATH_TMP_PROP)?.as_ptr(), CString::new(constants::PATH_TMP_PROP)?.as_ptr(),
CString::new(constants::PATH_MODULE_PROP)?.as_ptr(), CString::new(module_prop)?.as_ptr(),
std::ptr::null(), std::ptr::null(),
libc::MS_BIND, libc::MS_BIND,
std::ptr::null(), std::ptr::null(),

View File

@@ -10,7 +10,6 @@ use nix::{
use passfd::FdPassingExt; use passfd::FdPassingExt;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use std::ffi::c_char;
use std::fs; use std::fs;
use std::os::unix::{ use std::os::unix::{
net::{UnixListener, UnixStream}, net::{UnixListener, UnixStream},
@@ -64,8 +63,7 @@ pub fn entry() -> Result<()> {
} }
fn get_arch() -> Result<&'static str> { fn get_arch() -> Result<&'static str> {
let output = Command::new("getprop").arg("ro.product.cpu.abi").output()?; let system_arch = utils::get_property("ro.product.cpu.abi")?;
let system_arch = String::from_utf8(output.stdout)?;
if system_arch.contains("arm") { if system_arch.contains("arm") {
return Ok(lp_select!("armeabi-v7a", "arm64-v8a")); return Ok(lp_select!("armeabi-v7a", "arm64-v8a"));
} }
@@ -181,12 +179,8 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
Err(_) => break, Err(_) => break,
}; };
let tag = stream.read_string()?; let tag = stream.read_string()?;
let tag = std::ffi::CString::new(tag)?;
let message = stream.read_string()?; let message = stream.read_string()?;
let message = std::ffi::CString::new(message)?; utils::log_raw(level as i32, &tag, &message)?;
unsafe {
__android_log_print(level as i32, tag.as_ptr(), message.as_ptr());
}
} }
} }
DaemonSocketAction::ReadNativeBridge => { DaemonSocketAction::ReadNativeBridge => {
@@ -244,7 +238,3 @@ fn handle_daemon_action(mut stream: UnixStream, context: &Context) -> Result<()>
} }
Ok(()) Ok(())
} }
extern "C" {
fn __android_log_print(prio: i32, tag: *const c_char, fmt: *const c_char, ...) -> i32;
}