From 37d5b9e046071a1f10115e5aa9f11de249b0f692 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sat, 27 Sep 2025 19:33:20 +0800 Subject: [PATCH] kernel: Use the prctl command to provide switches for scanning functionality in user space --- kernel/core_hook.c | 79 ++++++++++++++++++++++++++++++++++++++--- kernel/ksu.h | 1 + kernel/throne_comm.c | 79 +++++++++++++++++++++++++++++++++++++++++ kernel/throne_comm.h | 10 ++++++ kernel/throne_tracker.c | 14 +++++--- 5 files changed, 174 insertions(+), 9 deletions(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 52791ef5..87fedf13 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -57,6 +57,8 @@ #include "kpm/kpm.h" #endif +bool ksu_uid_scanner_enabled = false; + #ifdef CONFIG_KSU_SUSFS bool susfs_is_allow_su(void) { @@ -315,10 +317,11 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry) pr_info("renameat: %s -> %s, new path: %s\n", old_dentry->d_iname, new_dentry->d_iname, buf); + if (ksu_uid_scanner_enabled) { + ksu_request_userspace_scan(); + } + track_throne(); - - // Also request userspace scan for next time - ksu_request_userspace_scan(); return 0; } @@ -350,6 +353,19 @@ static inline void nuke_ext4_sysfs(void) } #endif +static void init_uid_scanner(void) +{ + ksu_uid_init(); + do_load_throne_state(NULL); + + if (ksu_uid_scanner_enabled) { + int ret = ksu_throne_comm_init(); + if (ret != 0) { + pr_err("Failed to initialize throne communication: %d\n", ret); + } + } +} + int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { @@ -499,8 +515,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, post_fs_data_lock = true; pr_info("post-fs-data triggered\n"); on_post_fs_data(); - // Initialize throne communication - ksu_throne_comm_init(); + // Initialize UID scanner if enabled + init_uid_scanner(); // Initializing Dynamic Signatures ksu_dynamic_manager_init(); pr_info("Dynamic sign config loaded during post-fs-data\n"); @@ -1103,6 +1119,58 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, return 0; } + // UID Scanner control command + if (arg2 == CMD_ENABLE_UID_SCANNER) { + if (arg3 == 0) { + // Get current status + bool status = ksu_uid_scanner_enabled; + if (copy_to_user((void __user *)arg4, &status, sizeof(status))) { + pr_err("uid_scanner: copy status failed\n"); + return 0; + } + } else if (arg3 == 1) { + // Enable/Disable toggle + bool enabled = (arg4 != 0); + + if (enabled == ksu_uid_scanner_enabled) { + pr_info("uid_scanner: no need to change, already %s\n", + enabled ? "enabled" : "disabled"); + if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { + pr_err("uid_scanner: prctl reply error\n"); + } + return 0; + } + + if (enabled) { + // Enable UID scanner + int ret = ksu_throne_comm_init(); + if (ret != 0) { + pr_err("uid_scanner: failed to initialize: %d\n", ret); + return 0; + } + pr_info("uid_scanner: enabled\n"); + } else { + // Disable UID scanner + ksu_throne_comm_exit(); + pr_info("uid_scanner: disabled\n"); + } + + ksu_uid_scanner_enabled = enabled; + ksu_throne_comm_save_state(); + } else if (arg3 == 2) { + // Clear environment (force exit) + ksu_throne_comm_exit(); + ksu_uid_scanner_enabled = false; + ksu_throne_comm_save_state(); + pr_info("uid_scanner: environment cleared\n"); + } + + if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { + pr_err("uid_scanner: prctl reply error\n"); + } + return 0; + } + return 0; } @@ -1699,6 +1767,7 @@ void __init ksu_core_init(void) void ksu_core_exit(void) { + ksu_uid_exit(); ksu_throne_comm_exit(); #ifdef CONFIG_KSU_KPROBES_HOOK diff --git a/kernel/ksu.h b/kernel/ksu.h index 64163b87..aa92013a 100644 --- a/kernel/ksu.h +++ b/kernel/ksu.h @@ -31,6 +31,7 @@ #define CMD_GET_SUSFS_FEATURE_STATUS 102 #define CMD_DYNAMIC_MANAGER 103 #define CMD_GET_MANAGERS 104 +#define CMD_ENABLE_UID_SCANNER 105 #define EVENT_POST_FS_DATA 1 #define EVENT_BOOT_COMPLETED 2 diff --git a/kernel/throne_comm.c b/kernel/throne_comm.c index 10342347..e79da9b8 100644 --- a/kernel/throne_comm.c +++ b/kernel/throne_comm.c @@ -7,12 +7,18 @@ #include "klog.h" #include "throne_comm.h" +#include "kernel_compat.h" #define PROC_UID_SCANNER "ksu_uid_scanner" +#define UID_SCANNER_STATE_FILE "/data/adb/ksu/.uid_scanner" static struct proc_dir_entry *proc_entry = NULL; static struct workqueue_struct *scanner_wq = NULL; static struct work_struct scan_work; +static struct work_struct ksu_state_save_work; +static struct work_struct ksu_state_load_work; + +extern bool ksu_uid_scanner_enabled; // Signal userspace to rescan static bool need_rescan = false; @@ -38,6 +44,67 @@ void ksu_handle_userspace_update(void) pr_info("userspace uid list updated\n"); } +static void do_save_throne_state(struct work_struct *work) +{ + struct file *fp; + char state_char = ksu_uid_scanner_enabled ? '1' : '0'; + loff_t off = 0; + + fp = ksu_filp_open_compat(UID_SCANNER_STATE_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (IS_ERR(fp)) { + pr_err("save_throne_state create file failed: %ld\n", PTR_ERR(fp)); + return; + } + + if (ksu_kernel_write_compat(fp, &state_char, sizeof(state_char), &off) != sizeof(state_char)) { + pr_err("save_throne_state write failed\n"); + goto exit; + } + + pr_info("throne state saved: %s\n", ksu_uid_scanner_enabled ? "enabled" : "disabled"); + +exit: + filp_close(fp, 0); +} + +void do_load_throne_state(struct work_struct *work) +{ + struct file *fp; + char state_char; + loff_t off = 0; + ssize_t ret; + + fp = ksu_filp_open_compat(UID_SCANNER_STATE_FILE, O_RDONLY, 0); + if (IS_ERR(fp)) { + pr_info("throne state file not found, using default: disabled\n"); + ksu_uid_scanner_enabled = false; + return; + } + + ret = ksu_kernel_read_compat(fp, &state_char, sizeof(state_char), &off); + if (ret != sizeof(state_char)) { + pr_err("load_throne_state read err: %zd\n", ret); + ksu_uid_scanner_enabled = false; + goto exit; + } + + ksu_uid_scanner_enabled = (state_char == '1'); + pr_info("throne state loaded: %s\n", ksu_uid_scanner_enabled ? "enabled" : "disabled"); + +exit: + filp_close(fp, 0); +} + +bool ksu_throne_comm_load_state(void) +{ + return ksu_queue_work(&ksu_state_load_work); +} + +void ksu_throne_comm_save_state(void) +{ + ksu_queue_work(&ksu_state_save_work); +} + static int uid_scanner_show(struct seq_file *m, void *v) { if (need_rescan) { @@ -134,3 +201,15 @@ void ksu_throne_comm_exit(void) pr_info("throne communication cleaned up\n"); } + +int ksu_uid_init(void) +{ + INIT_WORK(&ksu_state_save_work, do_save_throne_state); + INIT_WORK(&ksu_state_load_work, do_load_throne_state); + return 0; +} + +void ksu_uid_exit(void) +{ + do_save_throne_state(NULL); +} \ No newline at end of file diff --git a/kernel/throne_comm.h b/kernel/throne_comm.h index eedf8c15..4deba2ab 100644 --- a/kernel/throne_comm.h +++ b/kernel/throne_comm.h @@ -9,4 +9,14 @@ int ksu_throne_comm_init(void); void ksu_throne_comm_exit(void); +int ksu_uid_init(void); + +void ksu_uid_exit(void); + +bool ksu_throne_comm_load_state(void); + +void ksu_throne_comm_save_state(void); + +void do_load_throne_state(struct work_struct *work); + #endif \ No newline at end of file diff --git a/kernel/throne_tracker.c b/kernel/throne_tracker.c index f6074698..a1d35a62 100644 --- a/kernel/throne_tracker.c +++ b/kernel/throne_tracker.c @@ -586,15 +586,21 @@ static bool is_uid_exist(uid_t uid, char *package, void *data) return exist; } +extern bool ksu_uid_scanner_enabled; + void track_throne(void) { struct list_head uid_list; INIT_LIST_HEAD(&uid_list); - pr_info("track_throne triggered, attempting whitelist read\n"); - - // Try read whitelist first - int ret = read_uid_whitelist(&uid_list); + int ret; + + if (ksu_uid_scanner_enabled) { + // Try read whitelist first + ret = read_uid_whitelist(&uid_list); + } else { + ret = -1; + } if (ret < 0) { pr_info("whitelist read failed (%d), request userspace scan, falling back to user_de \n", ret);