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 <rsuntk@yukiprjkt.my.id>
This commit is contained in:
backslashxx
2025-06-16 01:45:08 +07:00
committed by ShirkNeko
parent d13233f566
commit 2394fc67fc
2 changed files with 33 additions and 0 deletions

View File

@@ -62,6 +62,17 @@ ifeq ($(shell grep -q "int\s\+path_umount" $(srctree)/fs/namespace.c; echo $$?),
ccflags-y += -DKSU_HAS_PATH_UMOUNT ccflags-y += -DKSU_HAS_PATH_UMOUNT
endif 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 # Checks Samsung UH drivers
ifeq ($(shell grep -q "CONFIG_KDP_CRED" $(srctree)/kernel/cred.c; echo $$?),0) ifeq ($(shell grep -q "CONFIG_KDP_CRED" $(srctree)/kernel/cred.c; echo $$?),0)
ccflags-y += -DSAMSUNG_UH_DRIVER_EXIST ccflags-y += -DSAMSUNG_UH_DRIVER_EXIST

View File

@@ -726,12 +726,34 @@ static int ksu_task_fix_setuid(struct cred *new, const struct cred *old,
return ksu_handle_setuid(new, 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 #ifndef MODULE
static struct security_hook_list ksu_hooks[] = { static struct security_hook_list ksu_hooks[] = {
LSM_HOOK_INIT(task_prctl, ksu_task_prctl), LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
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),
#if !defined(KSU_HAS_DEVPTS_HANDLER) && !defined(CONFIG_KSU_KPROBES_HOOK)
LSM_HOOK_INIT(inode_permission, ksu_inode_permission), LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \
defined(CONFIG_IS_HW_HISI) || \ defined(CONFIG_IS_HW_HISI) || \
defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)