From e9ee2304d34983a810007e59505919ee809d07a2 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Wed, 22 Oct 2025 20:43:14 +0800 Subject: [PATCH] kernel: Extend sulog to also record system call logs --- kernel/core_hook.c | 67 +++++++++++++++++++ kernel/sucompat.c | 4 ++ kernel/sulog.c | 38 ++++++++++- kernel/sulog.h | 2 + .../sukisu/ultra/ui/screen/LogViewerScreen.kt | 7 ++ 5 files changed, 117 insertions(+), 1 deletion(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index d274fd82..ea8a36c0 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -417,6 +417,70 @@ static void init_uid_scanner(void) } } +static void sulog_prctl_cmd(uid_t uid, unsigned long cmd) +{ + const char *name = NULL; + + switch (cmd) { + case CMD_GRANT_ROOT: name = "prctl_grant_root"; break; + case CMD_BECOME_MANAGER: name = "prctl_become_manager"; break; + case CMD_GET_VERSION: name = "prctl_get_version"; break; + case CMD_GET_FULL_VERSION: name = "prctl_get_full_version"; break; + case CMD_SET_SEPOLICY: name = "prctl_set_sepolicy"; break; + case CMD_CHECK_SAFEMODE: name = "prctl_check_safemode"; break; + case CMD_GET_ALLOW_LIST: name = "prctl_get_allow_list"; break; + case CMD_GET_DENY_LIST: name = "prctl_get_deny_list"; break; + case CMD_UID_GRANTED_ROOT: name = "prctl_uid_granted_root"; break; + case CMD_UID_SHOULD_UMOUNT: name = "prctl_uid_should_umount"; break; + case CMD_IS_SU_ENABLED: name = "prctl_is_su_enabled"; break; + case CMD_ENABLE_SU: name = "prctl_enable_su"; break; +#ifdef CONFIG_KSU_MANUAL_SU + case CMD_ENABLE_KPM: name = "prctl_enable_kpm"; break; +#endif + case CMD_HOOK_TYPE: name = "prctl_hook_type"; break; + case CMD_DYNAMIC_MANAGER: name = "prctl_dynamic_manager"; break; + case CMD_GET_MANAGERS: name = "prctl_get_managers"; break; + case CMD_ENABLE_UID_SCANNER: name = "prctl_enable_uid_scanner"; break; + case CMD_REPORT_EVENT: name = "prctl_report_event"; break; + case CMD_SET_APP_PROFILE: name = "prctl_set_app_profile"; break; + case CMD_GET_APP_PROFILE: name = "prctl_get_app_profile"; break; + +#ifdef CONFIG_KPM + case CMD_SU_ESCALATION_REQUEST: name = "prctl_su_escalation_request"; break; + case CMD_ADD_PENDING_ROOT: name = "prctl_add_pending_root"; break; +#endif + +#ifdef CONFIG_KSU_SUSFS + case CMD_SUSFS_ADD_SUS_PATH: name = "prctl_susfs_add_sus_path"; break; + case CMD_SUSFS_ADD_SUS_PATH_LOOP: name = "prctl_susfs_add_sus_path_loop"; break; + case CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH: name = "prctl_susfs_set_android_data_root_path"; break; + case CMD_SUSFS_SET_SDCARD_ROOT_PATH: name = "prctl_susfs_set_sdcard_root_path"; break; + case CMD_SUSFS_ADD_SUS_MOUNT: name = "prctl_susfs_add_sus_mount"; break; + case CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS: name = "prctl_susfs_hide_sus_mnts_for_all_procs"; break; + case CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE: name = "prctl_susfs_umount_for_zygote_iso_service"; break; + case CMD_SUSFS_ADD_SUS_KSTAT: name = "prctl_susfs_add_sus_kstat"; break; + case CMD_SUSFS_UPDATE_SUS_KSTAT: name = "prctl_susfs_update_sus_kstat"; break; + case CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY: name = "prctl_susfs_add_sus_kstat_statically"; break; + case CMD_SUSFS_ADD_TRY_UMOUNT: name = "prctl_susfs_add_try_umount"; break; + case CMD_SUSFS_SET_UNAME: name = "prctl_susfs_set_uname"; break; + case CMD_SUSFS_ENABLE_LOG: name = "prctl_susfs_enable_log"; break; + case CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG: name = "prctl_susfs_set_cmdline_or_bootconfig"; break; + case CMD_SUSFS_ADD_OPEN_REDIRECT: name = "prctl_susfs_add_open_redirect"; break; + case CMD_SUSFS_SUS_SU: name = "prctl_susfs_sus_su"; break; + case CMD_SUSFS_SHOW_VERSION: name = "prctl_susfs_show_version"; break; + case CMD_SUSFS_SHOW_ENABLED_FEATURES: name = "prctl_susfs_show_enabled_features"; break; + case CMD_SUSFS_SHOW_VARIANT: name = "prctl_susfs_show_variant"; break; + case CMD_SUSFS_IS_SUS_SU_READY: name = "prctl_susfs_is_sus_su_ready"; break; + case CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE: name = "prctl_susfs_show_sus_su_working_mode"; break; + case CMD_SUSFS_ADD_SUS_MAP: name = "prctl_susfs_add_sus_map"; break; + case CMD_SUSFS_ENABLE_AVC_LOG_SPOOFING: name = "prctl_susfs_enable_avc_log_spoofing"; break; +#endif + + default: name = "prctl_unknown"; break; + } + + ksu_sulog_report_syscall(uid, NULL, name, NULL); +} int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) @@ -429,6 +493,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, u32 reply_ok = KERNEL_SU_OPTION; uid_t current_uid_val = current_uid().val; + sulog_prctl_cmd(current_uid().val, arg2); + #ifdef CONFIG_KSU_MANUAL_SU is_manual_su_cmd = (arg2 == CMD_SU_ESCALATION_REQUEST || arg2 == CMD_ADD_PENDING_ROOT); @@ -1008,6 +1074,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) current->pid); return 0; } + ksu_sulog_report_syscall(new_uid.val, NULL, "setuid", NULL); #ifdef CONFIG_KSU_DEBUG // umount the target mnt pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val, diff --git a/kernel/sucompat.c b/kernel/sucompat.c index c14f31ed..7ef384c8 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -70,6 +70,7 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (unlikely(!memcmp(path, su, sizeof(su)))) { + ksu_sulog_report_syscall(current_uid().val, NULL, "faccessat", path); pr_info("faccessat su->sh!\n"); *filename_user = sh_user_path(); } @@ -114,6 +115,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (unlikely(!memcmp(path, su, sizeof(su)))) { + ksu_sulog_report_syscall(current_uid().val, NULL, "newfstatat", path); pr_info("newfstatat su->sh!\n"); *filename_user = sh_user_path(); } @@ -155,6 +157,7 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, if (likely(memcmp(filename->name, su, sizeof(su)))) return 0; + ksu_sulog_report_syscall(current_uid_val, NULL, "execve", filename->name); ksu_sulog_report_su_attempt(current_uid_val, NULL, filename->name, is_allowed); if (!is_allowed) { @@ -192,6 +195,7 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user, if (likely(memcmp(path, su, sizeof(su)))) return 0; + ksu_sulog_report_syscall(current_uid_val, NULL, "execve", path); ksu_sulog_report_su_attempt(current_uid_val, NULL, path, is_allowed); if (!is_allowed) diff --git a/kernel/sulog.c b/kernel/sulog.c index effb17b1..a720d6d9 100644 --- a/kernel/sulog.c +++ b/kernel/sulog.c @@ -18,7 +18,7 @@ #define SULOG_PATH "/data/adb/ksu/log/sulog.log" #define SULOG_OLD_PATH "/data/adb/ksu/log/sulog.log.old" -#define SULOG_MAX_SIZE (16 * 1024 * 1024) // 16MB +#define SULOG_MAX_SIZE (128 * 1024 * 1024) // 128MB #define SULOG_ENTRY_MAX_LEN 512 #define SULOG_COMM_LEN 256 @@ -341,6 +341,42 @@ cleanup_mgr: if (log_buf) kfree(log_buf); } +void ksu_sulog_report_syscall(uid_t uid, const char *comm, + const char *syscall, const char *args) +{ + char *timestamp, *full_comm, *log_buf; + + if (!sulog_enabled) + return; + + timestamp = kmalloc(32, GFP_ATOMIC); + full_comm = kmalloc(SULOG_COMM_LEN, GFP_ATOMIC); + log_buf = kmalloc(SULOG_ENTRY_MAX_LEN, GFP_ATOMIC); + + if (!timestamp || !full_comm || !log_buf) { + pr_err("sulog: failed to allocate memory for syscall log\n"); + goto cleanup_mgr; + } + + get_timestamp(timestamp, 32); + get_full_comm(full_comm, SULOG_COMM_LEN); + + snprintf(log_buf, SULOG_ENTRY_MAX_LEN, + "[%s] SYSCALL: UID=%d COMM=%s SYSCALL=%s ARGS=%s PID=%d\n", + timestamp, uid, full_comm, + syscall ? syscall : "unknown", + args ? args : "none", + current->pid); + + sulog_add_entry(log_buf); + pr_info("sulog: %s", log_buf); + +cleanup_mgr: + if (timestamp) kfree(timestamp); + if (full_comm) kfree(full_comm); + if (log_buf) kfree(log_buf); +} + void ksu_sulog_set_enabled(bool enabled) { sulog_enabled = enabled; diff --git a/kernel/sulog.h b/kernel/sulog.h index 4498a8c1..0e43e001 100644 --- a/kernel/sulog.h +++ b/kernel/sulog.h @@ -11,6 +11,8 @@ void ksu_sulog_report_permission_check(uid_t uid, const char *comm, bool allowed void ksu_sulog_report_manager_operation(const char *operation, uid_t manager_uid, uid_t target_uid); +void ksu_sulog_report_syscall(uid_t uid, const char *comm, const char *syscall, const char *args); + void ksu_sulog_set_enabled(bool enabled); bool ksu_sulog_is_enabled(void); diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/LogViewerScreen.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/LogViewerScreen.kt index fdf64b1f..f9b8888d 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/LogViewerScreen.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/LogViewerScreen.kt @@ -60,6 +60,7 @@ enum class LogType(val displayName: String, val color: Color) { SU_GRANT("SU_GRANT", Color(0xFF4CAF50)), SU_EXEC("SU_EXEC", Color(0xFF2196F3)), PERM_CHECK("PERM_CHECK", Color(0xFFFF9800)), + SYSCALL("SYSCALL", Color(0xFF00BCD4)), MANAGER_OP("MANAGER_OP", Color(0xFF9C27B0)), UNKNOWN("UNKNOWN", Color(0xFF757575)) } @@ -626,6 +627,7 @@ private fun parseLogLine(line: String): LogEntry? { "SU_GRANT" -> LogType.SU_GRANT "SU_EXEC" -> LogType.SU_EXEC "PERM_CHECK" -> LogType.PERM_CHECK + "SYSCALL" -> LogType.SYSCALL "MANAGER_OP" -> LogType.MANAGER_OP else -> LogType.UNKNOWN } @@ -650,6 +652,11 @@ private fun parseLogLine(line: String): LogEntry? { val result: String = extractValue(details, "RESULT") ?: "" "Result: $result" } + LogType.SYSCALL -> { + val syscall = extractValue(details, "SYSCALL") ?: "" + val args = extractValue(details, "ARGS") ?: "" + "Syscall: $syscall, Args: $args" + } LogType.MANAGER_OP -> { val op: String = extractValue(details, "OP") ?: "" val managerUid: String = extractValue(details, "MANAGER_UID") ?: ""