From 04a1b8256426b14f4fd943134ba46c584eb54dff Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Mon, 22 Sep 2025 23:54:51 +0800 Subject: [PATCH] kernel: core_hook: intercept devpts via security_inode_permission LSM `ksu handles devpts with selinux lsm hook` - aviraxp - no, not yet, but yes we can, thats a good idea. This change tries to do that, so instead of hooking pts_unix98_lookup or devpts_get_priv, we just watch security_inode_permission, if its devpts, pass it along to the original handler. EDIT: define devpts super magic if its undefined - yeah I aint gonna include a conditional include of a header just for this - while we can just fully remove the macro and inline, readability loss is bad Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com> --- kernel/core_hook.c | 24 ++++++++++++++++++++---- kernel/sucompat.c | 15 +++++++++------ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 524fd95e..014145cc 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -1426,6 +1426,22 @@ static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred, } #endif +#ifndef DEVPTS_SUPER_MAGIC +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#endif + +extern int __ksu_handle_devpts(struct inode *inode); // sucompat.c + +int ksu_inode_permission(struct inode *inode, int mask) +{ + if (inode && inode->i_sb + && unlikely(inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) { + //pr_info("%s: handling devpts for: %s \n", __func__, current->comm); + __ksu_handle_devpts(inode); + } + return 0; +} + #ifdef CONFIG_COMPAT bool ksu_is_compat __read_mostly = false; #endif @@ -1472,13 +1488,13 @@ 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 LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ - defined(CONFIG_IS_HW_HISI) || \ - defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) - LSM_HOOK_INIT(key_permission, ksu_key_permission) + LSM_HOOK_INIT(inode_permission, ksu_inode_permission), #ifndef CONFIG_KSU_KPROBES_HOOK LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check), #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ + defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) + LSM_HOOK_INIT(key_permission, ksu_key_permission) }; void __init ksu_lsm_hook_init(void) diff --git a/kernel/sucompat.c b/kernel/sucompat.c index 82c73009..69425add 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -242,7 +242,13 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user, return 0; } +// dummified int ksu_handle_devpts(struct inode *inode) +{ + return 0; +} + +int __ksu_handle_devpts(struct inode *inode) { #ifndef CONFIG_KSU_KPROBES_HOOK @@ -260,20 +266,17 @@ int ksu_handle_devpts(struct inode *inode) return 0; } - if (!ksu_is_allow_uid(uid)) + if (likely(!ksu_is_allow_uid(uid))) return 0; - if (ksu_devpts_sid) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) || defined(KSU_OPTIONAL_SELINUX_INODE) struct inode_security_struct *sec = selinux_inode(inode); #else struct inode_security_struct *sec = (struct inode_security_struct *)inode->i_security; #endif - if (sec) { - sec->sid = ksu_devpts_sid; - } - } + if (ksu_devpts_sid && sec) + sec->sid = ksu_devpts_sid; return 0; }