new supercall impl (#511)
* refactor: replace throne tracker with ksud token
* use snprintf
* refactor: new supercall impl
- Import the sukisu command
* disable seccomp for supercall users
* kernel: fmt clear
* kernel: Enable macro protection for sulog
- Only enabled on kernel versions greater than 5.10.245
* kernel: Refactor kprobe hooks and implement LSM hooks for improved security handling
* debug mode
* kernel: Add functionality to generate and validate authentication tokens for cmd_su
* kernel: Simplified manual SU command processing for code
* kernel: replace renameat hook with fsnotify
* Revert "refactor: replace throne tracker with ksud token"
This reverts commit aa2cbbf9cd.
* kernel: fix compile
* kernel: fix compile below 6.0
* Fix compile err; Add become_manager
* kernel: install fd for manager automaticlly
- extend to import the corresponding command
* manager: new supercall impl
* temp changes for ksud
* ksud: fix compile
* fix wrong opcode
* kernel: fix compile
* kernel: Fixed hook type and KPM status retrieval errors
* kernel: Fixed potential null pointer issue with current->mm in kernel version 5.10
When calling get_full_comm() within system call hooks, current->mm may be null (prctl). A fallback mechanism for current->comm must be added beforehand to prevent null pointer dereferences when accessing mm->arg_start/arg_end.
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
* ksud: fix cargo check
* manager: Fixed an issue where the KSUD release and user-mode scanning switch failed to function correctly.
- kernel: fix spin lock mutual
kernel: Fixed potential null pointer issue with current->mm in kernel version 5.10
When calling get_full_comm() within system call hooks, current->mm may be null (prctl). A fallback mechanism for current->comm must be added beforehand to prevent null pointer dereferences when accessing mm->arg_start/arg_end.
kernel: try introduce like susfs's method to fix prctl delay
* seccomp: allow reboot
* use u32
* update clang-format
* 4 spaces save the world
* ksud: Fix build on macOS
* manager: bump minimal supported kernel.
- When get_hook_type is empty, display “Unknown”.
* Fix ksud build (#2841)
* try fix ksud
* fix for macos
* remove any
* Fix ksud build, take 3
* try fix allowlist
* bring lsm hook back
* fix: a lot again
* Fix ksud build, take 4 (#2846)
Remove init_driver_fd function for non-linux/android targets
* manager: Return to the native method via KSUd installation
* Merge with susfs-mian format
---------
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: Ylarod <me@ylarod.cn>
Co-authored-by: weishu <twsxtd@gmail.com>
Co-authored-by: AlexLiuDev233 <wzylin11@outlook.com>
Co-authored-by: Wang Han <416810799@qq.com>
This commit is contained in:
@@ -1,10 +1,133 @@
|
||||
const EVENT_POST_FS_DATA: u64 = 1;
|
||||
const EVENT_BOOT_COMPLETED: u64 = 2;
|
||||
const EVENT_MODULE_MOUNTED: u64 = 3;
|
||||
use std::fs;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use std::os::fd::RawFd;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
// Event constants
|
||||
const EVENT_POST_FS_DATA: u32 = 1;
|
||||
const EVENT_BOOT_COMPLETED: u32 = 2;
|
||||
const EVENT_MODULE_MOUNTED: u32 = 3;
|
||||
|
||||
const KSU_IOCTL_GRANT_ROOT: u32 = 0x4B01; // _IO('K', 1)
|
||||
const KSU_IOCTL_GET_INFO: u32 = 0x80084b02; // _IOR('K', 2, struct ksu_get_info_cmd)
|
||||
const KSU_IOCTL_REPORT_EVENT: u32 = 0x40044b03; // _IOW('K', 3, struct ksu_report_event_cmd)
|
||||
const KSU_IOCTL_SET_SEPOLICY: u32 = 0xc0104b04; // _IOWR('K', 4, struct ksu_set_sepolicy_cmd)
|
||||
const KSU_IOCTL_CHECK_SAFEMODE: u32 = 0x80014b05; // _IOR('K', 5, struct ksu_check_safemode_cmd)
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct GetInfoCmd {
|
||||
version: u32,
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct ReportEventCmd {
|
||||
event: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct SetSepolicyCmd {
|
||||
pub cmd: u64,
|
||||
pub arg: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct CheckSafemodeCmd {
|
||||
in_safe_mode: u8,
|
||||
}
|
||||
|
||||
// Global driver fd cache
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
static DRIVER_FD: OnceLock<RawFd> = OnceLock::new();
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
static INFO_CACHE: OnceLock<GetInfoCmd> = OnceLock::new();
|
||||
|
||||
const KSU_INSTALL_MAGIC1: u32 = 0xDEADBEEF;
|
||||
const KSU_INSTALL_MAGIC2: u32 = 0xCAFEBABE;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn scan_driver_fd() -> Option<RawFd> {
|
||||
let fd_dir = fs::read_dir("/proc/self/fd").ok()?;
|
||||
|
||||
for entry in fd_dir.flatten() {
|
||||
if let Ok(fd_num) = entry.file_name().to_string_lossy().parse::<i32>() {
|
||||
let link_path = format!("/proc/self/fd/{}", fd_num);
|
||||
if let Ok(target) = fs::read_link(&link_path) {
|
||||
let target_str = target.to_string_lossy();
|
||||
if target_str.contains("[ksu_driver]") {
|
||||
return Some(fd_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// Get cached driver fd
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn init_driver_fd() -> Option<RawFd> {
|
||||
let fd = scan_driver_fd();
|
||||
if fd.is_none() {
|
||||
let mut fd = -1;
|
||||
unsafe {
|
||||
libc::syscall(
|
||||
libc::SYS_reboot,
|
||||
KSU_INSTALL_MAGIC1,
|
||||
KSU_INSTALL_MAGIC2,
|
||||
0,
|
||||
&mut fd,
|
||||
);
|
||||
};
|
||||
if fd >= 0 { Some(fd) } else { None }
|
||||
} else {
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
// ioctl wrapper using libc
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
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));
|
||||
unsafe {
|
||||
#[cfg(not(target_env = "gnu"))]
|
||||
let ret = libc::ioctl(fd as libc::c_int, request as i32, arg);
|
||||
#[cfg(target_env = "gnu")]
|
||||
let ret = libc::ioctl(fd as libc::c_int, request as u64, arg);
|
||||
if ret < 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
fn ksuctl<T>(_request: u32, _arg: *mut T) -> std::io::Result<i32> {
|
||||
Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
|
||||
}
|
||||
|
||||
// API implementations
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn get_info() -> GetInfoCmd {
|
||||
*INFO_CACHE.get_or_init(|| {
|
||||
let mut cmd = GetInfoCmd {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
};
|
||||
let _ = ksuctl(KSU_IOCTL_GET_INFO, &mut cmd as *mut _);
|
||||
cmd
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn get_version() -> i32 {
|
||||
rustix::process::ksu_get_version()
|
||||
get_info().version as i32
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
@@ -13,22 +136,24 @@ pub fn get_version() -> i32 {
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn report_event(event: u64) {
|
||||
rustix::process::ksu_report_event(event)
|
||||
pub fn grant_root() -> std::io::Result<()> {
|
||||
ksuctl(KSU_IOCTL_GRANT_ROOT, std::ptr::null_mut::<u8>())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
fn report_event(_event: u64) {}
|
||||
pub fn grant_root() -> std::io::Result<()> {
|
||||
Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn check_kernel_safemode() -> bool {
|
||||
rustix::process::ksu_check_kernel_safemode()
|
||||
fn report_event(event: u32) {
|
||||
let mut cmd = ReportEventCmd { event };
|
||||
let _ = ksuctl(KSU_IOCTL_REPORT_EVENT, &mut cmd as *mut _);
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn check_kernel_safemode() -> bool {
|
||||
false
|
||||
}
|
||||
fn report_event(_event: u32) {}
|
||||
|
||||
pub fn report_post_fs_data() {
|
||||
report_event(EVENT_POST_FS_DATA);
|
||||
@@ -41,3 +166,21 @@ pub fn report_boot_complete() {
|
||||
pub fn report_module_mounted() {
|
||||
report_event(EVENT_MODULE_MOUNTED);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn check_kernel_safemode() -> bool {
|
||||
let mut cmd = CheckSafemodeCmd { in_safe_mode: 0 };
|
||||
let _ = ksuctl(KSU_IOCTL_CHECK_SAFEMODE, &mut cmd as *mut _);
|
||||
cmd.in_safe_mode != 0
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
pub fn check_kernel_safemode() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn set_sepolicy(cmd: &SetSepolicyCmd) -> std::io::Result<()> {
|
||||
let mut ioctl_cmd = *cmd;
|
||||
ksuctl(KSU_IOCTL_SET_SEPOLICY, &mut ioctl_cmd as *mut _)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -20,7 +20,7 @@ fn parse_single_word(input: &str) -> IResult<&str, &str> {
|
||||
take_while1(is_sepolicy_char).parse(input)
|
||||
}
|
||||
|
||||
fn parse_bracket_objs<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
fn parse_bracket_objs(input: &str) -> IResult<&str, SeObject<'_>> {
|
||||
let (input, (_, words, _)) = (
|
||||
tag("{"),
|
||||
take_while_m_n(1, 100, |c: char| is_sepolicy_char(c) || c.is_whitespace()),
|
||||
@@ -30,12 +30,12 @@ fn parse_bracket_objs<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
Ok((input, words.split_whitespace().collect()))
|
||||
}
|
||||
|
||||
fn parse_single_obj<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
fn parse_single_obj(input: &str) -> IResult<&str, SeObject<'_>> {
|
||||
let (input, word) = take_while1(is_sepolicy_char).parse(input)?;
|
||||
Ok((input, vec![word]))
|
||||
}
|
||||
|
||||
fn parse_star<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
fn parse_star(input: &str) -> IResult<&str, SeObject<'_>> {
|
||||
let (input, _) = tag("*").parse(input)?;
|
||||
Ok((input, vec!["*"]))
|
||||
}
|
||||
@@ -43,12 +43,12 @@ fn parse_star<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
// 1. a single sepolicy word
|
||||
// 2. { obj1 obj2 obj3 ...}
|
||||
// 3. *
|
||||
fn parse_seobj<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
fn parse_seobj(input: &str) -> IResult<&str, SeObject<'_>> {
|
||||
let (input, strs) = alt((parse_single_obj, parse_bracket_objs, parse_star)).parse(input)?;
|
||||
Ok((input, strs))
|
||||
}
|
||||
|
||||
fn parse_seobj_no_star<'a>(input: &'a str) -> IResult<&'a str, SeObject<'a>> {
|
||||
fn parse_seobj_no_star(input: &str) -> IResult<&str, SeObject<'_>> {
|
||||
let (input, strs) = alt((parse_single_obj, parse_bracket_objs)).parse(input)?;
|
||||
Ok((input, strs))
|
||||
}
|
||||
@@ -697,7 +697,12 @@ fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>, strict: bool) -> Resul
|
||||
let policies: Vec<AtomicStatement> = statement.try_into()?;
|
||||
|
||||
for policy in policies {
|
||||
if !rustix::process::ksu_set_policy(&FfiPolicy::from(policy)) {
|
||||
let ffi_policy = FfiPolicy::from(policy);
|
||||
let cmd = crate::ksucalls::SetSepolicyCmd {
|
||||
cmd: 0,
|
||||
arg: &ffi_policy as *const _ as u64,
|
||||
};
|
||||
if crate::ksucalls::set_sepolicy(&cmd).is_err() {
|
||||
log::warn!("apply rule: {statement:?} failed.");
|
||||
if strict {
|
||||
return Err(anyhow::anyhow!("apply rule {:?} failed.", statement));
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::{
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn grant_root(global_mnt: bool) -> Result<()> {
|
||||
rustix::process::ksu_grant_root()?;
|
||||
crate::ksucalls::grant_root()?;
|
||||
|
||||
let mut command = Command::new("sh");
|
||||
let command = unsafe {
|
||||
|
||||
Reference in New Issue
Block a user