ksud: Optimise ksud (#576)

* opt: Optimize printing for result isn't successful
- print chain && backtrace to stderr

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* ci(ksud): add CARGO_TERM_COLOR for build

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* fix(ksud): fix uninstall package name is `me.weishu.kernelsu`

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* fix(ksud): Reverted to a private function for get_kernel_version

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* chore: format code for magic_mount.rs

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* fix: fix rustfmt

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

* feat: Move the statement to the correct place && remove allow dead_code

Signed-off-by: Tools-app <localhost.hutao@gmail.com>

---------

Signed-off-by: Tools-app <localhost.hutao@gmail.com>
This commit is contained in:
生于生时 亡于亡刻
2025-11-15 18:25:17 +08:00
committed by GitHub
parent 04ca981e4d
commit 92a483d222
8 changed files with 108 additions and 99 deletions

View File

@@ -24,7 +24,7 @@ fn ensure_gki_kernel() -> Result<()> {
}
#[cfg(target_os = "android")]
pub fn get_kernel_version() -> Result<(i32, i32, i32)> {
fn get_kernel_version() -> Result<(i32, i32, i32)> {
let uname = rustix::system::uname();
let version = uname.release().to_string_lossy();
let re = Regex::new(r"(\d+)\.(\d+)\.(\d+)")?;

View File

@@ -625,7 +625,11 @@ pub fn run() -> Result<()> {
};
if let Err(e) = &result {
log::error!("Error: {e:?}");
for c in e.chain() {
log::error!("{c:#?}");
}
log::error!("{:#?}", e.backtrace());
}
result
}

View File

@@ -8,7 +8,7 @@ use std::{
use anyhow::{Result, anyhow, bail};
use notify::{RecursiveMode, Watcher};
use crate::ksucalls;
use crate::ksucalls::ksuctl;
pub const KPM_DIR: &str = "/data/adb/kpm";
@@ -20,6 +20,22 @@ const KPM_INFO: u64 = 5;
const KPM_CONTROL: u64 = 6;
const KPM_VERSION: u64 = 7;
const KSU_IOCTL_KPM: u32 = 0xc0004bc8; // _IOC(_IOC_READ|_IOC_WRITE, 'K', 200, 0)
#[repr(C)]
#[derive(Clone, Copy, Default)]
struct KsuKpmCmd {
pub control_code: u64,
pub arg1: u64,
pub arg2: u64,
pub result_code: u64,
}
fn kpm_ioctl(cmd: &mut KsuKpmCmd) -> std::io::Result<()> {
ksuctl(KSU_IOCTL_KPM, cmd as *mut _)?;
Ok(())
}
/// Convert raw kernel return code to `Result`.
#[inline(always)]
fn check_ret(rc: i32) -> Result<i32> {
@@ -35,14 +51,14 @@ pub fn kpm_load(path: &str, args: Option<&str>) -> Result<()> {
let args_c = args.map(CString::new).transpose()?;
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_LOAD,
arg1: path_c.as_ptr() as u64,
arg2: args_c.as_ref().map_or(0, |s| s.as_ptr() as u64),
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)?;
println!("Success");
Ok(())
@@ -53,14 +69,14 @@ pub fn kpm_unload(name: &str) -> Result<()> {
let name_c = CString::new(name)?;
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_UNLOAD,
arg1: name_c.as_ptr() as u64,
arg2: 0,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)?;
Ok(())
}
@@ -68,14 +84,14 @@ pub fn kpm_unload(name: &str) -> Result<()> {
/// Return loaded module count.
pub fn kpm_num() -> Result<i32> {
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_NUM,
arg1: 0,
arg2: 0,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
let n = check_ret(result)?;
println!("{n}");
Ok(n)
@@ -86,14 +102,14 @@ pub fn kpm_list() -> Result<()> {
let mut buf = vec![0u8; 1024];
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_LIST,
arg1: buf.as_mut_ptr() as u64,
arg2: buf.len() as u64,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)?;
print!("{}", buf2str(&buf));
Ok(())
@@ -105,14 +121,14 @@ pub fn kpm_info(name: &str) -> Result<()> {
let mut buf = vec![0u8; 256];
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_INFO,
arg1: name_c.as_ptr() as u64,
arg2: buf.as_mut_ptr() as u64,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)?;
println!("{}", buf2str(&buf));
Ok(())
@@ -124,14 +140,14 @@ pub fn kpm_control(name: &str, args: &str) -> Result<i32> {
let args_c = CString::new(args)?;
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_CONTROL,
arg1: name_c.as_ptr() as u64,
arg2: args_c.as_ptr() as u64,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)
}
@@ -140,14 +156,14 @@ pub fn kpm_version_loader() -> Result<()> {
let mut buf = vec![0u8; 1024];
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_VERSION,
arg1: buf.as_mut_ptr() as u64,
arg2: buf.len() as u64,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)?;
print!("{}", buf2str(&buf));
Ok(())
@@ -158,14 +174,14 @@ pub fn check_kpm_version() -> Result<String> {
let mut buf = vec![0u8; 1024];
let mut result: i32 = -1;
let mut cmd = ksucalls::KsuKpmCmd {
let mut cmd = KsuKpmCmd {
control_code: KPM_VERSION,
arg1: buf.as_mut_ptr() as u64,
arg2: buf.len() as u64,
result_code: &mut result as *mut i32 as u64,
};
ksucalls::kpm_ioctl(&mut cmd)?;
kpm_ioctl(&mut cmd)?;
check_ret(result)?;
let ver = buf2str(&buf);
if ver.is_empty() {

View File

@@ -17,10 +17,6 @@ const KSU_IOCTL_GET_FEATURE: u32 = 0xc0004b0d; // _IOC(_IOC_READ|_IOC_WRITE, 'K'
const KSU_IOCTL_SET_FEATURE: u32 = 0x40004b0e; // _IOC(_IOC_WRITE, 'K', 14, 0)
const KSU_IOCTL_GET_WRAPPER_FD: u32 = 0x40004b0f; // _IOC(_IOC_WRITE, 'K', 15, 0)
const KSU_IOCTL_MANAGE_MARK: u32 = 0xc0004b10; // _IOC(_IOC_READ|_IOC_WRITE, 'K', 16, 0)
#[allow(dead_code)]
const KSU_IOCTL_KPM: u32 = 0xc0004bc8; // _IOC(_IOC_READ|_IOC_WRITE, 'K', 200, 0)
#[allow(dead_code)]
const KSU_IOCTL_UMOUNT_MANAGER: u32 = 0xc0004b6b; // _IOC(_IOC_READ|_IOC_WRITE, 'K', 107, 0)
#[repr(C)]
#[derive(Clone, Copy, Default)]
@@ -134,7 +130,7 @@ fn init_driver_fd() -> Option<RawFd> {
// ioctl wrapper using libc
#[cfg(any(target_os = "linux", target_os = "android"))]
fn ksuctl<T>(request: u32, arg: *mut T) -> std::io::Result<i32> {
pub fn ksuctl<T>(request: u32, arg: *mut T) -> std::io::Result<i32> {
use std::io;
let fd = *DRIVER_FD.get_or_init(|| init_driver_fd().unwrap_or(-1));
@@ -298,59 +294,3 @@ pub fn mark_refresh() -> std::io::Result<()> {
ksuctl(KSU_IOCTL_MANAGE_MARK, &mut cmd as *mut _)?;
Ok(())
}
#[repr(C)]
#[derive(Clone, Copy, Default)]
#[allow(dead_code)]
pub struct KsuKpmCmd {
pub control_code: u64,
pub arg1: u64,
pub arg2: u64,
pub result_code: u64,
}
#[allow(dead_code)]
pub fn kpm_ioctl(cmd: &mut KsuKpmCmd) -> std::io::Result<()> {
ksuctl(KSU_IOCTL_KPM, cmd as *mut _)?;
Ok(())
}
#[repr(C)]
#[derive(Clone, Copy)]
#[allow(dead_code)]
pub struct UmountManagerCmd {
pub operation: u32,
pub path: [u8; 256],
pub check_mnt: u8,
pub flags: i32,
pub count: u32,
pub entries_ptr: u64,
}
#[allow(dead_code)]
impl Default for UmountManagerCmd {
fn default() -> Self {
UmountManagerCmd {
operation: 0,
path: [0; 256],
check_mnt: 0,
flags: 0,
count: 0,
entries_ptr: 0,
}
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(dead_code)]
pub fn umount_manager_ioctl(cmd: &UmountManagerCmd) -> std::io::Result<()> {
let mut ioctl_cmd = *cmd;
ksuctl(KSU_IOCTL_UMOUNT_MANAGER, &mut ioctl_cmd as *mut _)?;
Ok(())
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
#[allow(dead_code)]
pub fn umount_manager_ioctl(_cmd: &UmountManagerCmd) -> std::io::Result<()> {
Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
}

View File

@@ -60,7 +60,10 @@ struct Node {
}
impl Node {
fn collect_module_files<T: AsRef<Path>>(&mut self, module_dir: T) -> Result<bool> {
fn collect_module_files<P>(&mut self, module_dir: P) -> Result<bool>
where
P: AsRef<Path>,
{
let dir = module_dir.as_ref();
let mut has_file = false;
for entry in dir.read_dir()?.flatten() {
@@ -83,7 +86,10 @@ impl Node {
Ok(has_file)
}
fn new_root<T: ToString>(name: T) -> Self {
fn new_root<T>(name: T) -> Self
where
T: ToString,
{
Node {
name: name.to_string(),
file_type: Directory,
@@ -94,7 +100,10 @@ impl Node {
}
}
fn new_module<T: ToString>(name: T, entry: &DirEntry) -> Option<Self> {
fn new_module<T>(name: T, entry: &DirEntry) -> Option<Self>
where
T: ToString,
{
if let Ok(metadata) = entry.metadata() {
let path = entry.path();
let file_type = if metadata.file_type().is_char_device() && metadata.rdev() == 0 {
@@ -174,7 +183,10 @@ fn collect_module_files() -> Result<Option<Node>> {
}
}
fn clone_symlink<Src: AsRef<Path>, Dst: AsRef<Path>>(src: Src, dst: Dst) -> Result<()> {
fn clone_symlink<P>(src: P, dst: P) -> Result<()>
where
P: AsRef<Path>,
{
let src_symlink = read_link(src.as_ref())?;
symlink(&src_symlink, dst.as_ref())?;
lsetfilecon(dst.as_ref(), lgetfilecon(src.as_ref())?.as_str())?;
@@ -187,11 +199,10 @@ fn clone_symlink<Src: AsRef<Path>, Dst: AsRef<Path>>(src: Src, dst: Dst) -> Resu
Ok(())
}
fn mount_mirror<P: AsRef<Path>, WP: AsRef<Path>>(
path: P,
work_dir_path: WP,
entry: &DirEntry,
) -> Result<()> {
fn mount_mirror<P>(path: P, work_dir_path: P, entry: &DirEntry) -> Result<()>
where
P: AsRef<Path>,
{
let path = path.as_ref().join(entry.file_name());
let work_dir_path = work_dir_path.as_ref().join(entry.file_name());
let file_type = entry.file_type()?;
@@ -236,12 +247,11 @@ fn mount_mirror<P: AsRef<Path>, WP: AsRef<Path>>(
Ok(())
}
fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
path: P,
work_dir_path: WP,
current: Node,
has_tmpfs: bool,
) -> Result<()> {
fn do_magic_mount<P, WP>(path: P, work_dir_path: WP, current: Node, has_tmpfs: bool) -> Result<()>
where
P: AsRef<Path>,
WP: AsRef<Path>,
{
let mut current = current;
let path = path.as_ref().join(&current.name);
let work_dir_path = work_dir_path.as_ref().join(&current.name);

View File

@@ -1,12 +1,14 @@
use crate::ksucalls::UmountManagerCmd;
use anyhow::{Context, Result, anyhow};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::{Path, PathBuf};
use crate::ksucalls::ksuctl;
const MAGIC_NUMBER_HEADER: &[u8; 4] = b"KUMT";
const MAGIC_VERSION: u32 = 1;
const CONFIG_FILE: &str = "/data/adb/ksu/.umount";
const KSU_IOCTL_UMOUNT_MANAGER: u32 = 0xc0004b6b; // _IOC(_IOC_READ|_IOC_WRITE, 'K', 107, 0)
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct UmountEntry {
@@ -27,6 +29,30 @@ pub struct UmountManager {
defaults: Vec<UmountEntry>,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct UmountManagerCmd {
pub operation: u32,
pub path: [u8; 256],
pub check_mnt: u8,
pub flags: i32,
pub count: u32,
pub entries_ptr: u64,
}
impl Default for UmountManagerCmd {
fn default() -> Self {
UmountManagerCmd {
operation: 0,
path: [0; 256],
check_mnt: 0,
flags: 0,
count: 0,
entries_ptr: 0,
}
}
}
impl UmountManager {
pub fn new(config_path: Option<PathBuf>) -> Result<Self> {
let path = config_path.unwrap_or_else(|| PathBuf::from(CONFIG_FILE));
@@ -212,8 +238,7 @@ impl UmountManager {
cmd.path[..path_bytes.len()].copy_from_slice(path_bytes);
crate::ksucalls::umount_manager_ioctl(&cmd)
.context(format!("Failed to add entry: {}", entry.path))?;
umount_manager_ioctl(&cmd).context(format!("Failed to add entry: {}", entry.path))?;
Ok(())
}
@@ -274,6 +299,18 @@ pub fn list_umount_paths() -> Result<()> {
Ok(())
}
#[cfg(any(target_os = "linux", target_os = "android"))]
fn umount_manager_ioctl(cmd: &UmountManagerCmd) -> std::io::Result<()> {
let mut ioctl_cmd = *cmd;
ksuctl(KSU_IOCTL_UMOUNT_MANAGER, &mut ioctl_cmd as *mut _)?;
Ok(())
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn umount_manager_ioctl(_cmd: &UmountManagerCmd) -> std::io::Result<()> {
Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
}
pub fn clear_custom_paths() -> Result<()> {
let mut manager = init_umount_manager()?;
manager.clear_custom_entries()?;

View File

@@ -238,7 +238,7 @@ pub fn uninstall(magiskboot_path: Option<PathBuf>) -> Result<()> {
boot_patch::restore(None, magiskboot_path, true)?;
println!("- Uninstall KernelSU manager..");
Command::new("pm")
.args(["uninstall", "me.weishu.kernelsu"])
.args(["uninstall", "com.sukisu.ultra"])
.spawn()?;
println!("- Rebooting in 5 seconds..");
std::thread::sleep(std::time::Duration::from_secs(5));