Skip to content

Commit 7ca0a3a

Browse files
committed
kernel: kp_ksud: restore kprobes for early-boot and used-once hooks
since kprobes offer dynamic hooking and shit, this is going to be better on something that we only need temporarily. this still keeps whole sucompat onto manual hooks as those are performance sensitive, needed to be permanent and "timeable". as for these hooks that got hooked here they are only used either only at boot or on some, used only once. symbols hooked: security_bprm_check - this thing is only needed at boot, so we might as well put this dynamic this is needed for _ksud exec decision making and 32-on-64 detection. vfs_read - needed only at boot for read proxy-ing atrace.rc input_event - needed only up to like boot_complete, for 3-button-press safemode feature security_key_permission - needed for a keygrab on allowlist workaround for kernels below 4.10 and some sys_execve * - a substitute for security_bprm_check. this is deadcoded here, kept for reference purposes. -- for handling registration of those "LSM-hooks-being kprobed", we register once preempt is suspended. as for unregistration, we defer this once boot is completed and then have a kthread unregister everything. credits: some of these are just straight up copied from upstream. Tests: ximi mi a2 lite, arm64, Linux 4.9 samsung galaxy s3, arm, Linux 3.0 #26 Signed-off-by: backslashxx <[email protected]>
1 parent 295faf4 commit 7ca0a3a

File tree

6 files changed

+396
-2
lines changed

6 files changed

+396
-2
lines changed

kernel/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ config KSU
66
help
77
Enable kernel-level root privileges on Android System.
88

9+
config CONFIG_KSU_DYNAMIC_BOOT_HOOKS
10+
bool "Enable dynamic kprobes for early boot"
11+
depends on KPROBES
12+
depends on KALLSYMS
13+
default y
14+
help
15+
Use dynamic hooks via kprobes for functions needed only
16+
on early boot. Hooks are unregistered at boot complete
17+
to reduce overhead.
18+
919
config KSU_DEBUG
1020
bool "KernelSU debug mode"
1121
depends on KSU

kernel/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ kernelsu-objs += ksud.o
88
kernelsu-objs += embed_ksud.o
99
kernelsu-objs += kernel_compat.o
1010

11+
ifeq ($(CONFIG_KSU_DYNAMIC_BOOT_HOOKS),y)
12+
kernelsu-objs += kp_ksud.o
13+
endif
14+
1115
kernelsu-objs += selinux/selinux.o
1216
kernelsu-objs += selinux/sepolicy.o
1317
kernelsu-objs += selinux/rules.o

kernel/arch.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#ifndef __KSU_H_ARCH
2+
#define __KSU_H_ARCH
3+
4+
#include <linux/version.h>
5+
6+
#if defined(__aarch64__)
7+
8+
#define __PT_PARM1_REG regs[0]
9+
#define __PT_PARM2_REG regs[1]
10+
#define __PT_PARM3_REG regs[2]
11+
#define __PT_SYSCALL_PARM4_REG regs[3]
12+
#define __PT_CCALL_PARM4_REG regs[3]
13+
#define __PT_PARM5_REG regs[4]
14+
#define __PT_PARM6_REG regs[5]
15+
#define __PT_RET_REG regs[30]
16+
#define __PT_FP_REG regs[29] /* Works only with CONFIG_FRAME_POINTER */
17+
#define __PT_RC_REG regs[0]
18+
#define __PT_SP_REG sp
19+
#define __PT_IP_REG pc
20+
21+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
22+
#define SYS_EXECVE_SYMBOL "__arm64_sys_execve"
23+
#else
24+
#define SYS_EXECVE_SYMBOL "sys_execve"
25+
#endif
26+
27+
#elif defined(__arm__)
28+
29+
// https://elixir.bootlin.com/linux/v6.17-rc6/source/tools/lib/bpf/bpf_tracing.h
30+
#define __PT_PARM1_REG uregs[0]
31+
#define __PT_PARM2_REG uregs[1]
32+
#define __PT_PARM3_REG uregs[2]
33+
#define __PT_PARM4_REG uregs[3]
34+
35+
// seems to work atleast on 3.0 on samsung galaxy s3
36+
// nfi what im doing
37+
#define __PT_SYSCALL_PARM4_REG uregs[3]
38+
#define __PT_CCALL_PARM4_REG uregs[3]
39+
40+
#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG
41+
#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG
42+
#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG
43+
#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG
44+
#define __PT_PARM5_SYSCALL_REG uregs[4]
45+
#define __PT_PARM6_SYSCALL_REG uregs[5]
46+
#define __PT_PARM7_SYSCALL_REG uregs[6]
47+
48+
#define __PT_RET_REG uregs[14]
49+
#define __PT_FP_REG uregs[11] /* Works only with CONFIG_FRAME_POINTER */
50+
#define __PT_RC_REG uregs[0]
51+
#define __PT_SP_REG uregs[13]
52+
#define __PT_IP_REG uregs[12]
53+
54+
#define SYS_EXECVE_SYMBOL "sys_execve"
55+
56+
#elif defined(__x86_64__)
57+
58+
#define __PT_PARM1_REG di
59+
#define __PT_PARM2_REG si
60+
#define __PT_PARM3_REG dx
61+
/* syscall uses r10 for PARM4 */
62+
#define __PT_SYSCALL_PARM4_REG r10
63+
#define __PT_CCALL_PARM4_REG cx
64+
#define __PT_PARM5_REG r8
65+
#define __PT_PARM6_REG r9
66+
#define __PT_RET_REG sp
67+
#define __PT_FP_REG bp
68+
#define __PT_RC_REG ax
69+
#define __PT_SP_REG sp
70+
#define __PT_IP_REG ip
71+
72+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
73+
#define SYS_EXECVE_SYMBOL "__x64_sys_execve"
74+
#else
75+
#define SYS_EXECVE_SYMBOL "sys_execve"
76+
#endif
77+
78+
#else
79+
#error "Unsupported arch"
80+
#endif
81+
82+
/* allow some architecutres to override `struct pt_regs` */
83+
#ifndef __PT_REGS_CAST
84+
#define __PT_REGS_CAST(x) (x)
85+
#endif
86+
87+
#define PT_REGS_PARM1(x) (__PT_REGS_CAST(x)->__PT_PARM1_REG)
88+
#define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG)
89+
#define PT_REGS_PARM3(x) (__PT_REGS_CAST(x)->__PT_PARM3_REG)
90+
#define PT_REGS_SYSCALL_PARM4(x) (__PT_REGS_CAST(x)->__PT_SYSCALL_PARM4_REG)
91+
#define PT_REGS_CCALL_PARM4(x) (__PT_REGS_CAST(x)->__PT_CCALL_PARM4_REG)
92+
#define PT_REGS_PARM5(x) (__PT_REGS_CAST(x)->__PT_PARM5_REG)
93+
#define PT_REGS_PARM6(x) (__PT_REGS_CAST(x)->__PT_PARM6_REG)
94+
#define PT_REGS_RET(x) (__PT_REGS_CAST(x)->__PT_RET_REG)
95+
#define PT_REGS_FP(x) (__PT_REGS_CAST(x)->__PT_FP_REG)
96+
#define PT_REGS_RC(x) (__PT_REGS_CAST(x)->__PT_RC_REG)
97+
#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->__PT_SP_REG)
98+
#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->__PT_IP_REG)
99+
100+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
101+
#define PT_REAL_REGS(regs) ((struct pt_regs *)PT_REGS_PARM1(regs))
102+
#else
103+
#define PT_REAL_REGS(regs) ((regs))
104+
#endif
105+
106+
#endif

kernel/core_hook.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ static bool ksu_su_compat_enabled = true;
5151
extern void ksu_sucompat_init();
5252
extern void ksu_sucompat_exit();
5353

54+
#ifdef CONFIG_KSU_DYNAMIC_BOOT_HOOKS
55+
extern void unregister_kprobe_thread();
56+
#else
57+
void unregister_kprobe_thread() {}
58+
#endif
59+
5460
static inline bool is_allow_su()
5561
{
5662
if (is_manager()) {
@@ -417,6 +423,7 @@ LSM_HANDLER_TYPE ksu_handle_prctl(int option, unsigned long arg2, unsigned long
417423
if (!boot_complete_lock) {
418424
boot_complete_lock = true;
419425
pr_info("boot_complete triggered\n");
426+
unregister_kprobe_thread();
420427
}
421428
break;
422429
}
@@ -749,7 +756,7 @@ LSM_HANDLER_TYPE ksu_inode_permission(struct inode *inode, int mask)
749756
bool ksu_is_compat __read_mostly = false;
750757
#endif
751758

752-
LSM_HANDLER_TYPE ksu_bprm_check(struct linux_binprm *bprm)
759+
int ksu_bprm_check(struct linux_binprm *bprm)
753760
{
754761
char *filename = (char *)bprm->filename;
755762

@@ -786,7 +793,7 @@ LSM_HANDLER_TYPE ksu_bprm_check(struct linux_binprm *bprm)
786793

787794
// kernel 4.9 and older
788795
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
789-
LSM_HANDLER_TYPE ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
796+
int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
790797
unsigned perm)
791798
{
792799
if (init_session_keyring != NULL) {
@@ -827,10 +834,12 @@ static struct security_hook_list ksu_hooks[] = {
827834
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
828835
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
829836
LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
837+
#ifndef CONFIG_KSU_DYNAMIC_BOOT_HOOKS
830838
LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check),
831839
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
832840
LSM_HOOK_INIT(key_permission, ksu_key_permission)
833841
#endif
842+
#endif // CONFIG_KSU_DYNAMIC_BOOT_HOOKS
834843
};
835844

836845
void __init ksu_lsm_hook_init(void)

0 commit comments

Comments
 (0)