diff --git a/kernel/Kconfig b/kernel/Kconfig index a24a5b90..b492fcda 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -16,6 +16,13 @@ config KSU_DEBUG help Enable KernelSU debug mode. +config KSU_MANUAL_SU + bool "Use manual su" + depends on KSU + default y + help + Use manual su and authorize the corresponding command line and application via prctl + config KPM bool "Enable SukiSU KPM" depends on KSU && 64BIT diff --git a/kernel/Makefile b/kernel/Makefile index 8ef66e8a..c508cbd7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -9,7 +9,9 @@ kernelsu-objs += ksud.o kernelsu-objs += embed_ksud.o kernelsu-objs += kernel_compat.o kernelsu-objs += throne_comm.o +ifeq ($(CONFIG_KSU_MANUAL_SU), y) kernelsu-objs += manual_su.o +endif ifeq ($(CONFIG_KSU_TRACEPOINT_HOOK), y) kernelsu-objs += ksu_trace.o @@ -125,6 +127,22 @@ else $(info -- KPM is disabled) endif +ifeq ($(CONFIG_KSU_MANUAL_SU), y) +KSU_PW_POOL := abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 +KSU_PW_LEN := $(shell awk 'BEGIN{srand(); print int(rand()*9)+8}') + +ifeq ($(CONFIG_KSU), m) +KSU_SU_PASSWORD := CilloZako114514 +else +KSU_SU_PASSWORD := $(shell \ + tr -dc '$(KSU_PW_POOL)' selinux_domain); } +#ifdef CONFIG_KSU_MANUAL_SU void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid) { struct cred *newcreds; @@ -274,6 +278,7 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid) pr_info("cmd_su: privilege escalation completed for UID: %d, PID: %d\n", target_uid, target_pid); } +#endif int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry) { @@ -386,7 +391,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, if (!current->mm || current->in_execve) { return 0; } - +#ifdef CONFIG_KSU_MANUAL_SU if (arg2 == CMD_SU_ESCALATION_REQUEST) { uid_t target_uid = (uid_t)arg3; struct su_request_arg __user *user_req = (struct su_request_arg __user *)arg4; @@ -425,7 +430,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, pr_err("prctl: CMD_ADD_PENDING_ROOT reply error\n"); return 0; } - +#endif if (!from_root && !from_manager && !(is_allow_su() && is_system_bin_su())) { // only root or manager can access this interface @@ -1024,6 +1029,7 @@ int ksu_inode_permission(struct inode *inode, int mask) return 0; } +#ifdef CONFIG_KSU_MANUAL_SU static void ksu_try_escalate_for_uid(uid_t uid) { if (!is_pending_root(uid)) @@ -1032,6 +1038,7 @@ static void ksu_try_escalate_for_uid(uid_t uid) pr_info("pending_root: UID=%d temporarily allowed\n", uid); remove_pending_root(uid); } +#endif #ifdef CONFIG_COMPAT bool ksu_is_compat __read_mostly = false; @@ -1058,7 +1065,9 @@ int ksu_bprm_check(struct linux_binprm *bprm) ksu_handle_pre_ksud(filename); +#ifdef CONFIG_KSU_MANUAL_SU ksu_try_escalate_for_uid(current_uid().val); +#endif return 0; @@ -1071,12 +1080,14 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3, return -ENOSYS; } +#ifdef CONFIG_KSU_MANUAL_SU static int ksu_task_alloc(struct task_struct *task, unsigned long clone_flags) { ksu_try_escalate_for_uid(task_uid(task).val); return 0; } +#endif static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) @@ -1096,7 +1107,9 @@ static struct security_hook_list ksu_hooks[] = { LSM_HOOK_INIT(inode_rename, ksu_inode_rename), LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid), LSM_HOOK_INIT(inode_permission, ksu_inode_permission), +#ifdef CONFIG_KSU_MANUAL_SU LSM_HOOK_INIT(task_alloc, ksu_task_alloc), +#endif #ifndef CONFIG_KSU_KPROBES_HOOK LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check), #endif diff --git a/kernel/ksu.h b/kernel/ksu.h index 8c051648..1c6780a3 100644 --- a/kernel/ksu.h +++ b/kernel/ksu.h @@ -24,8 +24,10 @@ #define CMD_IS_SU_ENABLED 14 #define CMD_ENABLE_SU 15 +#ifdef CONFIG_KSU_MANUAL_SU #define CMD_SU_ESCALATION_REQUEST 50 #define CMD_ADD_PENDING_ROOT 51 +#endif #define CMD_GET_FULL_VERSION 0xC0FFEE1A diff --git a/kernel/manual_su.c b/kernel/manual_su.c index 9a87b21a..2f749cb8 100644 --- a/kernel/manual_su.c +++ b/kernel/manual_su.c @@ -12,7 +12,7 @@ #include "manager.h" #include "allowlist.h" -static const char *ksu_su_password = "zakozako"; +static const char *ksu_su_password = KSU_SU_PASSWORD; extern void escape_to_root_for_cmd_su(uid_t, pid_t); #define MAX_PENDING 16 #define REMOVE_DELAY_CALLS 150 @@ -42,12 +42,16 @@ int ksu_manual_su_escalate(uid_t target_uid, pid_t target_pid, return -EACCES; } char buf[64]; - if (strncpy_from_user(buf, user_password, sizeof(buf) - 1) < 0) + long copied; + + copied = ksu_strncpy_from_user_retry(buf, user_password, sizeof(buf) - 1); + if (copied < 0) return -EFAULT; - buf[sizeof(buf) - 1] = '\0'; + + buf[copied] = '\0'; if (strcmp(buf, ksu_su_password) != 0) { - pr_warn("manual_su: wrong password\n"); + pr_warn("manual_su: wrong password (input=%s, expect=%s)\n", buf, ksu_su_password); return -EACCES; }