From 2394fc67fc9d8e9d374df0815aca57b7541a83b2 Mon Sep 17 00:00:00 2001 From: backslashxx <118538522+backslashxx@users.noreply.github.com> Date: Mon, 16 Jun 2025 01:45:08 +0700 Subject: [PATCH] kernel: intercept devpts via security_inode_permission LSM * This changes: + Avoid conflicts with other devpts hooks. + We keep pts_unix98_pre for KPROBES for simplifying things. Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com> Signed-off-by: rsuntk --- kernel/Makefile | 11 +++++++++++ kernel/core_hook.c | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/kernel/Makefile b/kernel/Makefile index f4f226f6..f4b27a36 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -62,6 +62,17 @@ ifeq ($(shell grep -q "int\s\+path_umount" $(srctree)/fs/namespace.c; echo $$?), ccflags-y += -DKSU_HAS_PATH_UMOUNT endif +# we have pts_unix98/devpts_get_priv hook compat !! +KSU_HAS_DEVPTS_INODE := $(shell grep -q "int\s\+ksu_handle_devpts" $(srctree)/fs/devpts/inode.c; echo $$?) +KSU_HAS_PTS_UNIX98 := $(shell grep -q "int\s\+ksu_handle_devpts" $(srctree)/drivers/tty/pty.c; echo $$?) + +# It's impossible to have them both! neither KSU_HAS_DEVPTS_INODE/PTS_UNIX98 will detect 1 value! +# If both of them weren't exist, KSU_HAS_DEVPTS_HANDLER value gonna be 2. +$(eval KSU_DEVPTS_HANDLER_EXIST=$(shell expr $(KSU_HAS_DEVPTS_INODE) + $(KSU_HAS_PTS_UNIX98))) +ifeq ($(KSU_DEVPTS_HANDLER_EXIST),1) +ccflags-y += -DKSU_HAS_DEVPTS_HANDLER +endif + # Checks Samsung UH drivers ifeq ($(shell grep -q "CONFIG_KDP_CRED" $(srctree)/kernel/cred.c; echo $$?),0) ccflags-y += -DSAMSUNG_UH_DRIVER_EXIST diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 988816e1..2b67935f 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -726,12 +726,34 @@ static int ksu_task_fix_setuid(struct cred *new, const struct cred *old, return ksu_handle_setuid(new, old); } +/* + * Keep in mind, since kprobes already have pre handler, we must + * guard it with CONFIG_KSU_KPROBES_HOOK, although it is possible to + * disable kprobes pre handler, but this is way more simple. + * However, if you wanna use LSM hooks, feel free to fork. + */ +#if !defined(KSU_HAS_DEVPTS_HANDLER) && !defined(CONFIG_KSU_KPROBES_HOOK) +extern int ksu_handle_devpts(struct inode *inode); +static int ksu_inode_permission(struct inode *inode, int mask) +{ + if (unlikely(inode->i_sb && inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) { +#ifdef CONFIG_KSU_DEBUG + pr_info("%s: devpts inode accessed with mask: %x\n", __func__, mask); +#endif + ksu_handle_devpts(inode); + } + return 0; +} +#endif + #ifndef MODULE static struct security_hook_list ksu_hooks[] = { LSM_HOOK_INIT(task_prctl, ksu_task_prctl), LSM_HOOK_INIT(inode_rename, ksu_inode_rename), LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid), +#if !defined(KSU_HAS_DEVPTS_HANDLER) && !defined(CONFIG_KSU_KPROBES_HOOK) LSM_HOOK_INIT(inode_permission, ksu_inode_permission), +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ defined(CONFIG_IS_HW_HISI) || \ defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)