diff --git a/kernel/Kconfig b/kernel/Kconfig index d7557e36..9ea09c0c 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -22,14 +22,6 @@ config KSU_MULTI_MANAGER_SUPPORT help Enable multi KernelSU manager support -config KSU_MANUAL_HOOK - bool "Manual hooking GKI kernels without kprobes" - depends on KSU && KSU != m - default n - help - If enabled, Hook required KernelSU syscalls with manually-patched function. - If disabled, Hook required KernelSU syscalls with Kernel-probe. - config KSU_ALLOWLIST_WORKAROUND bool "KernelSU Session Keyring Init workaround" depends on KSU @@ -49,13 +41,40 @@ config KSU_CMDLINE config KPM bool "Enable SukiSU KPM" depends on KSU && 64BIT + select KALLSYMS + select KALLSYMS_ALL default n help Enabling this option will activate the KPM feature of SukiSU. This option is suitable for scenarios where you need to force KPM to be enabled. but it may affect system stability. - select KALLSYMS - select KALLSYMS_ALL + +choice + prompt "KernelSU hook type" + depends on KSU + default KSU_KPROBES_HOOK + help + Hook type for KernelSU + +config KSU_KPROBES_HOOK + bool "Hook KernelSU with Kprobes" + depends on KPROBES + help + If enabled, Hook required KernelSU syscalls with Kernel-probe. + +config KSU_TRACEPOINT_HOOK + bool "Hook KernelSU with Tracepoint" + depends on TRACEPOINTS + help + If enabled, Hook required KernelSU syscalls with Tracepoint. + +config KSU_MANUAL_HOOK + bool "Hook KernelSU manually" + depends on KSU != m + help + If enabled, Hook required KernelSU syscalls with manually-patched function. + +endchoice menu "KernelSU - SUSFS" config KSU_SUSFS diff --git a/kernel/Makefile b/kernel/Makefile index 2f9d48e7..3b6d860e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -9,6 +9,10 @@ kernelsu-objs += ksud.o kernelsu-objs += embed_ksud.o kernelsu-objs += kernel_compat.o +ifeq ($(strip $(CONFIG_KSU_TRACEPOINT_HOOK)),y) +kernelsu-objs += ksu_trace.o +endif + kernelsu-objs += selinux/selinux.o kernelsu-objs += selinux/sepolicy.o kernelsu-objs += selinux/rules.o @@ -17,6 +21,7 @@ ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h obj-$(CONFIG_KSU) += kernelsu.o +obj-$(CONFIG_KSU_TRACEPOINT_HOOK) += ksu_trace_export.o obj-$(CONFIG_KPM) += kpm/ @@ -71,11 +76,12 @@ endif ccflags-y += -DKSU_VERSION=$(KSU_VERSION) ccflags-y += -DKSU_VERSION_FULL=\"$(KSU_VERSION_FULL)\" -ifeq ($(strip $(CONFIG_KSU_MANUAL_HOOK)),y) -$(info -- SukiSU: CONFIG_KSU_MANUAL_HOOK) -else +ifeq ($(strip $(CONFIG_KSU_KPROBES_HOOK)),y) $(info -- SukiSU: CONFIG_KSU_KPROBES_HOOK) -ccflags-y += -DCONFIG_KSU_KPROBES_HOOK +else ifeq ($(strip $(CONFIG_KSU_TRACEPOINT_HOOK)),y) +$(info -- SukiSU: CONFIG_KSU_TRACEPOINT_HOOK) +else ifeq ($(strip $(CONFIG_KSU_MANUAL_HOOK)),y) +$(info -- SukiSU: CONFIG_KSU_MANUAL_HOOK) endif KERNEL_VERSION := $(VERSION).$(PATCHLEVEL) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 5b81c2da..955d0e2e 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -607,10 +607,12 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, if (arg2 == CMD_HOOK_TYPE) { const char *hook_type; -#ifdef CONFIG_KSU_MANUAL_HOOK - hook_type = "Manual"; -#elif defined(CONFIG_KSU_KPROBES_HOOK) +#if defined(CONFIG_KSU_KPROBES_HOOK) hook_type = "Kprobes"; +#elif defined(CONFIG_KSU_TRACEPOINT_HOOK) + hook_type = "Tracepoint"; +#elif defined(CONFIG_KSU_MANUAL_HOOK) + hook_type = "Manual"; #else hook_type = "Unknown"; #endif diff --git a/kernel/ksu.c b/kernel/ksu.c index 7f688cd2..bf080ec8 100644 --- a/kernel/ksu.c +++ b/kernel/ksu.c @@ -58,6 +58,10 @@ extern void ksu_sucompat_init(); extern void ksu_sucompat_exit(); extern void ksu_ksud_init(); extern void ksu_ksud_exit(); +#ifdef CONFIG_KSU_TRACEPOINT_HOOK +extern void ksu_trace_register(); +extern void ksu_trace_unregister(); +#endif int __init ksu_kernelsu_init(void) { @@ -100,6 +104,10 @@ int __init ksu_kernelsu_init(void) pr_alert("KPROBES is disabled, KernelSU may not work, please check https://kernelsu.org/guide/how-to-integrate-for-non-gki.html"); #endif +#ifdef CONFIG_KSU_TRACEPOINT_HOOK + ksu_trace_register(); +#endif + #ifdef MODULE #ifndef CONFIG_KSU_DEBUG kobject_del(&THIS_MODULE->mkobj.kobj); @@ -124,6 +132,11 @@ void ksu_kernelsu_exit(void) #ifdef CONFIG_KSU_KPROBES_HOOK ksu_ksud_exit(); #endif + +#ifdef CONFIG_KSU_TRACEPOINT_HOOK + ksu_trace_unregister(); +#endif + ksu_sucompat_exit(); ksu_core_exit(); diff --git a/kernel/ksu_trace.c b/kernel/ksu_trace.c new file mode 100644 index 00000000..5da68913 --- /dev/null +++ b/kernel/ksu_trace.c @@ -0,0 +1,90 @@ +#include "ksu_trace.h" + + +// extern kernelsu functions +extern bool ksu_execveat_hook __read_mostly; +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags); +extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags); +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, int *flags); +extern bool ksu_vfs_read_hook __read_mostly; +extern int ksu_handle_sys_read(unsigned int fd, char __user **buf_ptr, size_t *count_ptr); +extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags); +extern bool ksu_input_hook __read_mostly; +extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value); +extern int ksu_handle_devpts(struct inode*); +// end kernelsu functions + + +// tracepoint callback functions +void ksu_trace_execveat_hook_callback(void *data, int *fd, struct filename **filename_ptr, + void *argv, void *envp, int *flags) +{ + if (unlikely(ksu_execveat_hook)) + ksu_handle_execveat(fd, filename_ptr, argv, envp, flags); + else + ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL); +} + +void ksu_trace_execveat_sucompat_hook_callback(void *data, int *fd, struct filename **filename_ptr, + void *argv, void *envp, int *flags) +{ + if (!ksu_execveat_hook) + ksu_handle_execveat_sucompat(fd, filename_ptr, argv, envp, flags); +} + +void ksu_trace_faccessat_hook_callback(void *data, int *dfd, const char __user **filename_user, + int *mode, int *flags) +{ + ksu_handle_faccessat(dfd, filename_user, mode, flags); +} + +void ksu_trace_sys_read_hook_callback(void *data, unsigned int fd, char __user **buf_ptr, + size_t *count_ptr) +{ + if (unlikely(ksu_vfs_read_hook)) + ksu_handle_sys_read(fd, buf_ptr, count_ptr); +} + +void ksu_trace_stat_hook_callback(void *data, int *dfd, const char __user **filename_user, + int *flags) +{ + ksu_handle_stat(dfd, filename_user, flags); +} + +void ksu_trace_input_hook_callback(void *data, unsigned int *type, unsigned int *code, + int *value) +{ + if (unlikely(ksu_input_hook)) + ksu_handle_input_handle_event(type, code, value); +} + +void ksu_trace_devpts_hook_callback(void *data, struct inode *inode) +{ + ksu_handle_devpts(inode); +} +// end tracepoint callback functions + + +// register tracepoint callback functions +void ksu_trace_register(void) +{ + register_trace_ksu_trace_execveat_hook(ksu_trace_execveat_hook_callback, NULL); + register_trace_ksu_trace_execveat_sucompat_hook(ksu_trace_execveat_sucompat_hook_callback, NULL); + register_trace_ksu_trace_faccessat_hook(ksu_trace_faccessat_hook_callback, NULL); + register_trace_ksu_trace_sys_read_hook(ksu_trace_sys_read_hook_callback, NULL); + register_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, NULL); + register_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback, NULL); + register_trace_ksu_trace_devpts_hook(ksu_trace_devpts_hook_callback, NULL); +} + +// unregister tracepoint callback functions +void ksu_trace_unregister(void) +{ + unregister_trace_ksu_trace_execveat_hook(ksu_trace_execveat_hook_callback, NULL); + unregister_trace_ksu_trace_execveat_sucompat_hook(ksu_trace_execveat_sucompat_hook_callback, NULL); + unregister_trace_ksu_trace_faccessat_hook(ksu_trace_faccessat_hook_callback, NULL); + unregister_trace_ksu_trace_sys_read_hook(ksu_trace_sys_read_hook_callback, NULL); + unregister_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, NULL); + unregister_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback, NULL); + unregister_trace_ksu_trace_devpts_hook(ksu_trace_devpts_hook_callback, NULL); +} diff --git a/kernel/ksu_trace.h b/kernel/ksu_trace.h new file mode 100644 index 00000000..db279892 --- /dev/null +++ b/kernel/ksu_trace.h @@ -0,0 +1,45 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ksu_trace + +#if !defined(_KSU_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _KSU_TRACE_H + +#include +#include + +DECLARE_TRACE(ksu_trace_execveat_hook, + TP_PROTO(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags), + TP_ARGS(fd, filename_ptr, argv, envp, flags)); + +DECLARE_TRACE(ksu_trace_execveat_sucompat_hook, + TP_PROTO(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags), + TP_ARGS(fd, filename_ptr, argv, envp, flags)); + +DECLARE_TRACE(ksu_trace_faccessat_hook, + TP_PROTO(int *dfd, const char __user **filename_user, int *mode, int *flags), + TP_ARGS(dfd, filename_user, mode, flags)); + +DECLARE_TRACE(ksu_trace_sys_read_hook, + TP_PROTO(unsigned int fd, char __user **buf_ptr, size_t *count_ptr), + TP_ARGS(fd, buf_ptr, count_ptr)); + +DECLARE_TRACE(ksu_trace_stat_hook, + TP_PROTO(int *dfd, const char __user **filename_user, int *flags), + TP_ARGS(dfd, filename_user, flags)); + +DECLARE_TRACE(ksu_trace_input_hook, + TP_PROTO(unsigned int *type, unsigned int *code, int *value), + TP_ARGS(type, code, value)); + +DECLARE_TRACE(ksu_trace_devpts_hook, + TP_PROTO(struct inode *inode), + TP_ARGS(inode)); + +#endif /* _KSU_TRACE_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE ksu_trace + +#include diff --git a/kernel/ksu_trace_export.c b/kernel/ksu_trace_export.c new file mode 100644 index 00000000..0f21cbb0 --- /dev/null +++ b/kernel/ksu_trace_export.c @@ -0,0 +1,10 @@ +#define CREATE_TRACE_POINTS +#include "ksu_trace.h" + +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_execveat_hook); +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_execveat_sucompat_hook); +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_faccessat_hook); +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_sys_read_hook); +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_stat_hook); +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_input_hook); +EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_devpts_hook);