ksud: Fixed inconsistent parameter passing in kpm_prctl

This commit is contained in:
ShirkNeko
2025-10-06 22:02:59 +08:00
parent c9c7a5f4e3
commit 04b603394a

View File

@@ -1,7 +1,7 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use libc::{c_char, c_int, c_void, prctl}; use libc::{c_int, c_ulong, prctl};
use notify::{RecursiveMode, Watcher}; use notify::{RecursiveMode, Watcher};
use std::ffi::{CStr, CString, OsStr}; use std::ffi::{CString, OsStr};
use std::fs; use std::fs;
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@@ -9,130 +9,158 @@ use std::ptr;
pub const KPM_DIR: &str = "/data/adb/kpm"; pub const KPM_DIR: &str = "/data/adb/kpm";
const KSU_OPTIONS: u32 = 0xdeadbeef; const KSU_OPTIONS: c_int = 0xdeadbeef_u32 as c_int;
const SUKISU_KPM_LOAD: i32 = 28; const SUKISU_KPM_LOAD: c_int = 28;
const SUKISU_KPM_UNLOAD: i32 = 29; const SUKISU_KPM_UNLOAD: c_int = 29;
const SUKISU_KPM_NUM: i32 = 30; const SUKISU_KPM_NUM: c_int = 30;
const SUKISU_KPM_LIST: i32 = 31; const SUKISU_KPM_LIST: c_int = 31;
const SUKISU_KPM_INFO: i32 = 32; const SUKISU_KPM_INFO: c_int = 32;
const SUKISU_KPM_CONTROL:i32 = 33; const SUKISU_KPM_CONTROL:c_int = 33;
const SUKISU_KPM_VERSION:i32 = 34; const SUKISU_KPM_VERSION:c_int = 34;
#[inline(always)] #[inline(always)]
unsafe fn kpm_prctl( fn check_out(out: c_int) -> Result<c_int> {
cmd: i32, if out < 0 {
arg1: *const c_void, bail!("KPM error: {}", std::io::Error::from_raw_os_error(-out));
arg2: *const c_void,
) -> Result<i32> {
let mut out: c_int = -1;
let ret = unsafe {
prctl(
KSU_OPTIONS as c_int,
cmd as c_int,
arg1,
arg2,
&mut out as *mut c_int as *mut c_void,
)
};
if ret != 0 || out < 0 {
bail!("KPM prctl error: {}", std::io::Error::from_raw_os_error(-out));
} }
Ok(out) Ok(out)
} }
fn str_to_cstr<R, F: FnOnce(*const c_char) -> R>(s: &str, f: F) -> Result<R> {
let cs = CString::new(s)?;
Ok(f(cs.as_ptr()))
}
fn cbuf_to_string(buf: &[u8]) -> String {
unsafe { CStr::from_ptr(buf.as_ptr() as *const c_char) }
.to_string_lossy()
.into_owned()
}
pub fn kpm_load(path: &str, args: Option<&str>) -> Result<()> { pub fn kpm_load(path: &str, args: Option<&str>) -> Result<()> {
str_to_cstr(path, |p_path| { let path_c = CString::new(path)?;
let _args_cstring; let args_c = args.map(CString::new).transpose()?;
let p_args = match args {
Some(a) => { let mut out: c_int = -1;
_args_cstring = CString::new(a)?; unsafe {
_args_cstring.as_ptr() prctl(
} KSU_OPTIONS,
None => ptr::null(), SUKISU_KPM_LOAD,
}; path_c.as_ptr() as c_ulong,
unsafe { kpm_prctl(SUKISU_KPM_LOAD, p_path as _, p_args as _) }?; args_c.as_ref()
println!("Success"); .map_or(ptr::null(), |s| s.as_ptr()) as c_ulong,
Ok(()) &mut out as *mut c_int as c_ulong,
})? );
}
check_out(out)?;
println!("Success");
Ok(())
} }
pub fn kpm_unload(name: &str) -> Result<()> { pub fn kpm_unload(name: &str) -> Result<()> {
let _ = str_to_cstr(name, |p| unsafe { let name_c = CString::new(name)?;
kpm_prctl(SUKISU_KPM_UNLOAD, p as _, ptr::null()) let mut out: c_int = -1;
})?; unsafe {
prctl(
KSU_OPTIONS,
SUKISU_KPM_UNLOAD,
name_c.as_ptr() as c_ulong,
0,
&mut out as *mut c_int as c_ulong,
);
}
check_out(out)?;
Ok(()) Ok(())
} }
pub fn kpm_num() -> Result<i32> { pub fn kpm_num() -> Result<i32> {
let n = unsafe { kpm_prctl(SUKISU_KPM_NUM, ptr::null(), ptr::null())? }; let mut out: c_int = -1;
unsafe {
prctl(
KSU_OPTIONS,
SUKISU_KPM_NUM,
0,
0,
&mut out as *mut c_int as c_ulong,
);
}
let n = check_out(out)?;
println!("{}", n); println!("{}", n);
Ok(n) Ok(n)
} }
pub fn kpm_list() -> Result<()> { pub fn kpm_list() -> Result<()> {
let mut buf = vec![0u8; 1024]; let mut buf = vec![0u8; 1024];
let mut out: c_int = -1;
unsafe { unsafe {
kpm_prctl( prctl(
KSU_OPTIONS,
SUKISU_KPM_LIST, SUKISU_KPM_LIST,
buf.as_mut_ptr() as _, buf.as_mut_ptr() as c_ulong,
buf.len() as *const c_void, buf.len() as c_ulong,
)?; &mut out as *mut c_int as c_ulong,
);
} }
print!("{}", cbuf_to_string(&buf)); check_out(out)?;
print!("{}", buf2string(&buf));
Ok(()) Ok(())
} }
pub fn kpm_info(name: &str) -> Result<()> { pub fn kpm_info(name: &str) -> Result<()> {
let name_c = CString::new(name)?;
let mut buf = vec![0u8; 256]; let mut buf = vec![0u8; 256];
let _ = str_to_cstr(name, |p| unsafe { let mut out: c_int = -1;
kpm_prctl(SUKISU_KPM_INFO, p as _, buf.as_mut_ptr() as _) unsafe {
})?; prctl(
println!("{}", cbuf_to_string(&buf)); KSU_OPTIONS,
SUKISU_KPM_INFO,
name_c.as_ptr() as c_ulong,
buf.as_mut_ptr() as c_ulong,
&mut out as *mut c_int as c_ulong,
);
}
check_out(out)?;
println!("{}", buf2string(&buf));
Ok(()) Ok(())
} }
pub fn kpm_control(name: &str, args: &str) -> Result<i32> { pub fn kpm_control(name: &str, args: &str) -> Result<i32> {
str_to_cstr(name, |p_name| { let name_c = CString::new(name)?;
str_to_cstr(args, |p_args| unsafe { let args_c = CString::new(args)?;
kpm_prctl(SUKISU_KPM_CONTROL, p_name as _, p_args as _) let mut out: c_int = -1;
})? unsafe {
})? prctl(
KSU_OPTIONS,
SUKISU_KPM_CONTROL,
name_c.as_ptr() as c_ulong,
args_c.as_ptr() as c_ulong,
&mut out as *mut c_int as c_ulong,
);
}
check_out(out)?;
Ok(out)
} }
pub fn kpm_version_loader() -> Result<()> { pub fn kpm_version_loader() -> Result<()> {
let mut buf = vec![0u8; 1024]; let mut buf = vec![0u8; 1024];
let mut out: c_int = -1;
unsafe { unsafe {
kpm_prctl( prctl(
KSU_OPTIONS,
SUKISU_KPM_VERSION, SUKISU_KPM_VERSION,
buf.as_mut_ptr() as _, buf.as_mut_ptr() as c_ulong,
buf.len() as *const c_void, buf.len() as c_ulong,
)?; &mut out as *mut c_int as c_ulong,
);
} }
print!("{}", cbuf_to_string(&buf)); check_out(out)?;
print!("{}", buf2string(&buf));
Ok(()) Ok(())
} }
pub fn check_kpm_version() -> Result<String> { pub fn check_kpm_version() -> Result<String> {
let mut buf = vec![0u8; 1024]; let mut buf = vec![0u8; 1024];
let mut out: c_int = -1;
unsafe { unsafe {
kpm_prctl( prctl(
KSU_OPTIONS,
SUKISU_KPM_VERSION, SUKISU_KPM_VERSION,
buf.as_mut_ptr() as _, buf.as_mut_ptr() as c_ulong,
buf.len() as *const c_void, buf.len() as c_ulong,
)?; &mut out as *mut c_int as c_ulong,
);
} }
let ver = cbuf_to_string(&buf); check_out(out)?;
let ver = buf2string(&buf);
if ver.is_empty() || ver.starts_with("Error") { if ver.is_empty() || ver.starts_with("Error") {
bail!("KPM: Invalid version response: {}", ver); bail!("KPM: Invalid version response: {}", ver);
} }
@@ -153,7 +181,7 @@ pub fn ensure_kpm_dir() -> Result<()> {
} }
pub fn start_kpm_watcher() -> Result<()> { pub fn start_kpm_watcher() -> Result<()> {
check_kpm_version()?; check_kpm_version()?; // 版本不对直接返回
ensure_kpm_dir()?; ensure_kpm_dir()?;
if crate::utils::is_safe_mode() { if crate::utils::is_safe_mode() {
log::warn!("KPM: Safe mode removing all KPM modules"); log::warn!("KPM: Safe mode removing all KPM modules");
@@ -261,3 +289,11 @@ pub fn load_kpm_modules() -> Result<()> {
log::info!("KPM: Load done ok: {}, failed: {}", ok, ng); log::info!("KPM: Load done ok: {}, failed: {}", ok, ng);
Ok(()) Ok(())
} }
fn buf2string(buf: &[u8]) -> String {
unsafe {
std::ffi::CStr::from_ptr(buf.as_ptr() as *const _)
.to_string_lossy()
.into_owned()
}
}