From 0d55990b986ae7988855e02a6ff2062b601ca45b Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Thu, 23 Oct 2025 01:49:35 +0800 Subject: [PATCH] kernel: Add a UID blacklist feature to restrict the operational permissions of specific users --- kernel/sulog.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++--- kernel/sulog.h | 4 +++ 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/kernel/sulog.c b/kernel/sulog.c index a720d6d9..69261163 100644 --- a/kernel/sulog.c +++ b/kernel/sulog.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "klog.h" #include "kernel_compat.h" @@ -21,6 +23,36 @@ #define SULOG_MAX_SIZE (128 * 1024 * 1024) // 128MB #define SULOG_ENTRY_MAX_LEN 512 #define SULOG_COMM_LEN 256 +#define DEDUP_ENTRIES 256 +#define DEDUP_SECS 60 + +struct dedup_key { + u32 crc; + uid_t uid; + u8 type; + u8 _pad[1]; +}; + +struct dedup_entry { + struct dedup_key key; + u64 ts_ns; +}; + +static struct dedup_entry dedup_tbl[DEDUP_ENTRIES]; +static DEFINE_SPINLOCK(dedup_lock); + +enum { + DEDUP_SU_GRANT = 0, + DEDUP_SU_ATTEMPT, + DEDUP_PERM_CHECK, + DEDUP_MANAGER_OP, + DEDUP_SYSCALL, +}; + +static inline u32 dedup_calc_hash(const char *content, size_t len) +{ + return crc32(0, content, len); +} struct sulog_entry { struct list_head list; @@ -94,6 +126,35 @@ static void get_full_comm(char *comm_buf, size_t buf_len) comm_buf[buf_len - 1] = '\0'; } +static bool dedup_should_print(uid_t uid, u8 type, + const char *content, size_t len) +{ + struct dedup_key key = { + .crc = dedup_calc_hash(content, len), + .uid = uid, + .type = type, + }; + u64 now = ktime_get_ns(); + u64 delta_ns = DEDUP_SECS * NSEC_PER_SEC; + + u32 idx = key.crc & (DEDUP_ENTRIES - 1); + spin_lock(&dedup_lock); + + struct dedup_entry *e = &dedup_tbl[idx]; + if (e->key.crc == key.crc && + e->key.uid == key.uid && + e->key.type == key.type && + (now - e->ts_ns) < delta_ns) { + spin_unlock(&dedup_lock); + return false; + } + + e->key = key; + e->ts_ns = now; + spin_unlock(&dedup_lock); + return true; +} + static void sulog_work_handler(struct work_struct *work) { struct file *fp; @@ -220,9 +281,11 @@ void ksu_sulog_report_su_grant(uid_t uid, const char *comm, const char *method) "[%s] SU_GRANT: UID=%d COMM=%s METHOD=%s PID=%d\n", timestamp, uid, full_comm, method ? method : "unknown", current->pid); + + if (!dedup_should_print(uid, DEDUP_SU_GRANT, log_buf, strlen(log_buf))) + goto cleanup_grant; sulog_add_entry(log_buf); - pr_info("sulog: %s", log_buf); cleanup_grant: if (timestamp) kfree(timestamp); @@ -260,9 +323,11 @@ void ksu_sulog_report_su_attempt(uid_t uid, const char *comm, const char *target timestamp, uid, full_comm, target_path ? target_path : "unknown", success ? "SUCCESS" : "DENIED", current->pid); + + if (!dedup_should_print(uid, DEDUP_SU_GRANT, log_buf, strlen(log_buf))) + goto cleanup_attempt; sulog_add_entry(log_buf); - pr_info("sulog: %s", log_buf); cleanup_attempt: if (timestamp) kfree(timestamp); @@ -299,6 +364,9 @@ void ksu_sulog_report_permission_check(uid_t uid, const char *comm, bool allowed "[%s] PERM_CHECK: UID=%d COMM=%s RESULT=%s PID=%d\n", timestamp, uid, full_comm, allowed ? "ALLOWED" : "DENIED", current->pid); + + if (!dedup_should_print(uid, DEDUP_SU_GRANT, log_buf, strlen(log_buf))) + goto cleanup_perm; sulog_add_entry(log_buf); @@ -331,9 +399,11 @@ void ksu_sulog_report_manager_operation(const char *operation, uid_t manager_uid "[%s] MANAGER_OP: OP=%s MANAGER_UID=%d TARGET_UID=%d PID=%d\n", timestamp, operation ? operation : "unknown", manager_uid, target_uid, current->pid); + + if (!dedup_should_print(manager_uid, DEDUP_SU_GRANT, log_buf, strlen(log_buf))) + goto cleanup_mgr; sulog_add_entry(log_buf); - pr_info("sulog: %s", log_buf); cleanup_mgr: if (timestamp) kfree(timestamp); @@ -368,8 +438,10 @@ void ksu_sulog_report_syscall(uid_t uid, const char *comm, args ? args : "none", current->pid); + if (!dedup_should_print(uid, DEDUP_SU_GRANT, log_buf, strlen(log_buf))) + goto cleanup_mgr; + sulog_add_entry(log_buf); - pr_info("sulog: %s", log_buf); cleanup_mgr: if (timestamp) kfree(timestamp); diff --git a/kernel/sulog.h b/kernel/sulog.h index 0e43e001..7f859dd2 100644 --- a/kernel/sulog.h +++ b/kernel/sulog.h @@ -16,6 +16,10 @@ void ksu_sulog_report_syscall(uid_t uid, const char *comm, const char *syscall, void ksu_sulog_set_enabled(bool enabled); bool ksu_sulog_is_enabled(void); +void uid_blacklist_add(uid_t uid); +bool uid_blacklist_contains(uid_t uid); +void uid_blacklist_clear(void); + int ksu_sulog_init(void); void ksu_sulog_exit(void);