From 3f4c23a34f4f2d3011a0bb0b6a14a8f10bd18b7d Mon Sep 17 00:00:00 2001 From: Rifat Azad Date: Thu, 24 Jul 2025 01:24:20 +0600 Subject: [PATCH] kernel: allow only perms for /{system | vendor | product | system_ext}/bin/su path kernel: guard kernelnosu perms if not using KSU_KPROBES_HOOK --- kernel/core_hook.c | 65 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 478c0805..0d0a67fd 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -255,14 +255,32 @@ static void nuke_ext4_sysfs() { path_put(&path); } -static bool is_system_bin_su() +static bool is_system_bin_su(void) { - // YES in_execve becomes 0 when it succeeds. - if (!current->mm || current->in_execve) - return false; + static const char *su_paths[] = { + "/system/bin/su", + "/vendor/bin/su", + "/product/bin/su", + "/system_ext/bin/su", + "/odm/bin/su", + "/system/xbin/su", + "/system_ext/xbin/su" + }; + char path_buf[256]; + char *pathname; + int i; - // quick af check - return (current->mm->exe_file && !strcmp(current->mm->exe_file->f_path.dentry->d_name.name, "su")); + struct mm_struct *mm = current->mm; + if (mm && mm->exe_file) { + pathname = d_path(&mm->exe_file->f_path, path_buf, sizeof(path_buf)); + if (!IS_ERR(pathname)) { + for (i = 0; i < ARRAY_SIZE(su_paths); i++) { + if (strcmp(pathname, su_paths[i]) == 0) + return true; + } + } + } + return false; } int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, @@ -287,11 +305,18 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, bool from_root = 0 == current_uid().val; bool from_manager = is_manager(); +#ifdef CONFIG_KSU_KPROBES_HOOK if (!from_root && !from_manager && !(is_allow_su() && is_system_bin_su())) { // only root or manager can access this interface return 0; } +#else + if (!from_root && !from_manager) { + // only root or manager can access this interface + return 0; + } +#endif #ifdef CONFIG_KSU_DEBUG pr_info("option: 0x%x, cmd: %ld\n", option, arg2); @@ -457,6 +482,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, return 0; } +#ifdef CONFIG_KSU_KPROBES_HOOK if (arg2 == CMD_ENABLE_SU) { bool enabled = (arg3 != 0); if (enabled == ksu_su_compat_enabled) { @@ -480,6 +506,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, return 0; } +#endif // all other cmds are for 'root manager' if (!from_manager) { @@ -534,6 +561,32 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, } return 0; } +#ifndef CONFIG_KSU_KPROBES_HOOK + if (arg2 == CMD_ENABLE_SU) { + bool enabled = (arg3 != 0); + if (enabled == ksu_su_compat_enabled) { + pr_info("cmd enable su but no need to change.\n"); + if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly + pr_err("prctl reply error, cmd: %lu\n", arg2); + } + return 0; + } + + if (enabled) { + ksu_sucompat_init(); + } else { + ksu_sucompat_exit(); + } + ksu_su_compat_enabled = enabled; + + if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) { + pr_err("prctl reply error, cmd: %lu\n", arg2); + } + + return 0; + } +#endif + return 0; }