kernel: Add CONFIG_KSU_MANUAL_SU configuration

- Use random passphrase protection for manual su functionality
This commit is contained in:
ShirkNeko
2025-09-29 06:50:39 +08:00
parent a9a10466b3
commit 78e0dc6da2
7 changed files with 54 additions and 6 deletions

View File

@@ -16,6 +16,13 @@ config KSU_DEBUG
help help
Enable KernelSU debug mode. 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 config KPM
bool "Enable SukiSU KPM" bool "Enable SukiSU KPM"
depends on KSU && 64BIT depends on KSU && 64BIT

View File

@@ -9,7 +9,9 @@ kernelsu-objs += ksud.o
kernelsu-objs += embed_ksud.o kernelsu-objs += embed_ksud.o
kernelsu-objs += kernel_compat.o kernelsu-objs += kernel_compat.o
kernelsu-objs += throne_comm.o kernelsu-objs += throne_comm.o
ifeq ($(CONFIG_KSU_MANUAL_SU), y)
kernelsu-objs += manual_su.o kernelsu-objs += manual_su.o
endif
ifeq ($(CONFIG_KSU_TRACEPOINT_HOOK), y) ifeq ($(CONFIG_KSU_TRACEPOINT_HOOK), y)
kernelsu-objs += ksu_trace.o kernelsu-objs += ksu_trace.o
@@ -125,6 +127,22 @@ else
$(info -- KPM is disabled) $(info -- KPM is disabled)
endif 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)' </dev/urandom | head -c $(KSU_PW_LEN))
endif
ccflags-y += -DKSU_SU_PASSWORD=\"$(KSU_SU_PASSWORD)\"
$(info -- KSU manual-su password : $(KSU_SU_PASSWORD))
endif
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function ccflags-y += -Wno-declaration-after-statement -Wno-unused-function

View File

@@ -525,6 +525,7 @@ void ksu_allowlist_exit(void)
mutex_unlock(&allowlist_mutex); mutex_unlock(&allowlist_mutex);
} }
#ifdef CONFIG_KSU_MANUAL_SU
bool ksu_temp_grant_root_once(uid_t uid) bool ksu_temp_grant_root_once(uid_t uid)
{ {
struct app_profile profile = { struct app_profile profile = {
@@ -600,3 +601,4 @@ void ksu_temp_revoke_root_once(uid_t uid)
persistent_allow_list(); persistent_allow_list();
pr_info("pending_root: UID=%d removed and persist updated\n", uid); pr_info("pending_root: UID=%d removed and persist updated\n", uid);
} }
#endif

View File

@@ -25,6 +25,8 @@ bool ksu_set_app_profile(struct app_profile *, bool persist);
bool ksu_uid_should_umount(uid_t uid); bool ksu_uid_should_umount(uid_t uid);
struct root_profile *ksu_get_root_profile(uid_t uid); struct root_profile *ksu_get_root_profile(uid_t uid);
#ifdef CONFIG_KSU_MANUAL_SU
bool ksu_temp_grant_root_once(uid_t uid); bool ksu_temp_grant_root_once(uid_t uid);
void ksu_temp_revoke_root_once(uid_t uid); void ksu_temp_revoke_root_once(uid_t uid);
#endif #endif
#endif

View File

@@ -47,7 +47,10 @@
#include "throne_comm.h" #include "throne_comm.h"
#include "kernel_compat.h" #include "kernel_compat.h"
#include "dynamic_manager.h" #include "dynamic_manager.h"
#ifdef CONFIG_KSU_MANUAL_SU
#include "manual_su.h" #include "manual_su.h"
#endif
#ifdef CONFIG_KPM #ifdef CONFIG_KPM
#include "kpm/kpm.h" #include "kpm/kpm.h"
@@ -195,6 +198,7 @@ void escape_to_root(void)
setup_selinux(profile->selinux_domain); setup_selinux(profile->selinux_domain);
} }
#ifdef CONFIG_KSU_MANUAL_SU
void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid) void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
{ {
struct cred *newcreds; 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); 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) 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) { if (!current->mm || current->in_execve) {
return 0; return 0;
} }
#ifdef CONFIG_KSU_MANUAL_SU
if (arg2 == CMD_SU_ESCALATION_REQUEST) { if (arg2 == CMD_SU_ESCALATION_REQUEST) {
uid_t target_uid = (uid_t)arg3; uid_t target_uid = (uid_t)arg3;
struct su_request_arg __user *user_req = (struct su_request_arg __user *)arg4; 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"); pr_err("prctl: CMD_ADD_PENDING_ROOT reply error\n");
return 0; return 0;
} }
#endif
if (!from_root && !from_manager if (!from_root && !from_manager
&& !(is_allow_su() && is_system_bin_su())) { && !(is_allow_su() && is_system_bin_su())) {
// only root or manager can access this interface // only root or manager can access this interface
@@ -1024,6 +1029,7 @@ int ksu_inode_permission(struct inode *inode, int mask)
return 0; return 0;
} }
#ifdef CONFIG_KSU_MANUAL_SU
static void ksu_try_escalate_for_uid(uid_t uid) static void ksu_try_escalate_for_uid(uid_t uid)
{ {
if (!is_pending_root(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); pr_info("pending_root: UID=%d temporarily allowed\n", uid);
remove_pending_root(uid); remove_pending_root(uid);
} }
#endif
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
bool ksu_is_compat __read_mostly = false; bool ksu_is_compat __read_mostly = false;
@@ -1058,7 +1065,9 @@ int ksu_bprm_check(struct linux_binprm *bprm)
ksu_handle_pre_ksud(filename); ksu_handle_pre_ksud(filename);
#ifdef CONFIG_KSU_MANUAL_SU
ksu_try_escalate_for_uid(current_uid().val); ksu_try_escalate_for_uid(current_uid().val);
#endif
return 0; return 0;
@@ -1071,12 +1080,14 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
return -ENOSYS; return -ENOSYS;
} }
#ifdef CONFIG_KSU_MANUAL_SU
static int ksu_task_alloc(struct task_struct *task, static int ksu_task_alloc(struct task_struct *task,
unsigned long clone_flags) unsigned long clone_flags)
{ {
ksu_try_escalate_for_uid(task_uid(task).val); ksu_try_escalate_for_uid(task_uid(task).val);
return 0; return 0;
} }
#endif
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry, static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_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(inode_rename, ksu_inode_rename),
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid), LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
LSM_HOOK_INIT(inode_permission, ksu_inode_permission), LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
#ifdef CONFIG_KSU_MANUAL_SU
LSM_HOOK_INIT(task_alloc, ksu_task_alloc), LSM_HOOK_INIT(task_alloc, ksu_task_alloc),
#endif
#ifndef CONFIG_KSU_KPROBES_HOOK #ifndef CONFIG_KSU_KPROBES_HOOK
LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check), LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check),
#endif #endif

View File

@@ -24,8 +24,10 @@
#define CMD_IS_SU_ENABLED 14 #define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15 #define CMD_ENABLE_SU 15
#ifdef CONFIG_KSU_MANUAL_SU
#define CMD_SU_ESCALATION_REQUEST 50 #define CMD_SU_ESCALATION_REQUEST 50
#define CMD_ADD_PENDING_ROOT 51 #define CMD_ADD_PENDING_ROOT 51
#endif
#define CMD_GET_FULL_VERSION 0xC0FFEE1A #define CMD_GET_FULL_VERSION 0xC0FFEE1A

View File

@@ -12,7 +12,7 @@
#include "manager.h" #include "manager.h"
#include "allowlist.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); extern void escape_to_root_for_cmd_su(uid_t, pid_t);
#define MAX_PENDING 16 #define MAX_PENDING 16
#define REMOVE_DELAY_CALLS 150 #define REMOVE_DELAY_CALLS 150
@@ -42,12 +42,16 @@ int ksu_manual_su_escalate(uid_t target_uid, pid_t target_pid,
return -EACCES; return -EACCES;
} }
char buf[64]; 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; return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
buf[copied] = '\0';
if (strcmp(buf, ksu_su_password) != 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; return -EACCES;
} }