diff --git a/apd/src/cli.rs b/apd/src/cli.rs index 6664e8b02..d0bbc3cec 100644 --- a/apd/src/cli.rs +++ b/apd/src/cli.rs @@ -7,7 +7,7 @@ use android_logger::Config; use log::LevelFilter; use crate::{defs, event, module, supercall, utils}; - +use std::ffi::{CString, CStr}; /// APatch cli #[derive(Parser, Debug)] #[command(author, version = defs::VERSION_CODE, about, long_about = None)] @@ -30,6 +30,11 @@ enum Commands { #[command(subcommand)] command: Module, }, + /// Manage Kernel Patch modules + Kpm { + #[command(subcommand)] + command: Kpmsub, + }, /// Trigger `post-fs-data` event PostFsData, @@ -79,6 +84,17 @@ enum Module { /// list all modules List, } +#[derive(clap::Subcommand, Debug)] +enum Kpmsub { + /// Load Kernelpath module + Load { + // super_key + key: String, + // kpm module path + path: String + }, + +} pub fn run() -> Result<()> { #[cfg(target_os = "android")] @@ -118,6 +134,25 @@ pub fn run() -> Result<()> { Commands::UidListener => event::start_uid_listener(), + Commands::Kpm { command } => { + match command { + Kpmsub::Load { key,path } => { + let key_cstr = CString::new(key).map_err(|_| anyhow::anyhow!("Invalid key string"))?; + let path_cstr = CString::new(path).map_err(|_| anyhow::anyhow!("Invalid path string"))?; + let ret = supercall::sc_kpm_load(key_cstr.as_c_str(),path_cstr.as_c_str(),None,std::ptr::null_mut()); + if ret < 0 { + Err(anyhow::anyhow!("System call failed with error code {}", ret)) + } else { + Ok(()) + } + + } + _ => Err(anyhow::anyhow!("Unsupported command")), + + } + + } + Commands::Module { command } => { #[cfg(any(target_os = "linux", target_os = "android"))] { diff --git a/apd/src/supercall.rs b/apd/src/supercall.rs index c965c8b38..f8dedf16f 100644 --- a/apd/src/supercall.rs +++ b/apd/src/supercall.rs @@ -32,6 +32,7 @@ const SUPERCALL_SU_NUMS: c_long = 0x1102; const SUPERCALL_SU_LIST: c_long = 0x1103; const SUPERCALL_SU_RESET_PATH: c_long = 0x1111; const SUPERCALL_SU_GET_SAFEMODE: c_long = 0x1112; +const SUPERCALL_KPM_LOAD: c_long = 0x1020; const SUPERCALL_SCONTEXT_LEN: usize = 0x60; @@ -144,7 +145,22 @@ fn sc_su(key: &CStr, profile: &SuProfile) -> c_long { ) as c_long } } +pub fn sc_kpm_load(key: &CStr, path: &CStr, args: Option<&CStr>, reserved: *mut c_void) -> c_long { + if key.to_bytes().is_empty() || path.to_bytes().is_empty() { + return (-EINVAL).into(); + } + unsafe { + syscall( + __NR_SUPERCALL, + key.as_ptr(), + ver_and_cmd(SUPERCALL_KPM_LOAD), + path.as_ptr(), + args.map_or(std::ptr::null(), |a| a.as_ptr()), + reserved, + ) as c_long + } +} fn sc_su_reset_path(key: &CStr, path: &CStr) -> c_long { if key.to_bytes().is_empty() || path.to_bytes().is_empty() { return (-EINVAL).into();