kernel: Use the prctl command to provide switches for scanning functionality in user space
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user