diff --git a/kernel/core_hook.c b/kernel/core_hook.c index fafbabff..ea6f715d 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -831,6 +831,19 @@ static int ksu_task_fix_setuid(struct cred *new, const struct cred *old, } #ifndef MODULE + +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; +} + static struct security_hook_list ksu_hooks[] = { LSM_HOOK_INIT(task_prctl, ksu_task_prctl), LSM_HOOK_INIT(inode_rename, ksu_inode_rename), diff --git a/kernel/ksu_trace.c b/kernel/ksu_trace.c index 870e826d..ce48c045 100644 --- a/kernel/ksu_trace.c +++ b/kernel/ksu_trace.c @@ -11,6 +11,7 @@ extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int 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 int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value); +extern int ksu_handle_devpts(struct inode*); // end kernelsu functions @@ -56,6 +57,11 @@ void ksu_trace_input_hook_callback(void *data, unsigned int *type, unsigned int 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 @@ -68,6 +74,7 @@ void ksu_trace_register(void) 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 @@ -79,4 +86,5 @@ void ksu_trace_unregister(void) 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 index 75200f98..db279892 100644 --- a/kernel/ksu_trace.h +++ b/kernel/ksu_trace.h @@ -31,6 +31,10 @@ 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 diff --git a/kernel/ksu_trace_export.c b/kernel/ksu_trace_export.c index 7fb1b1bc..0f21cbb0 100644 --- a/kernel/ksu_trace_export.c +++ b/kernel/ksu_trace_export.c @@ -7,3 +7,4 @@ 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); diff --git a/kernel/sucompat.c b/kernel/sucompat.c index b29d4972..57e0d151 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -189,6 +189,47 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user, return 0; } +static int ksu_inline_handle_devpts(struct inode *inode) +{ + if (!current->mm) { + return 0; + } + + uid_t uid = current_uid().val; + if (uid % 100000 < 10000) { + // not untrusted_app, ignore it + return 0; + } + + if (!ksu_is_allow_uid(uid)) + return 0; + + if (ksu_devpts_sid) { + struct inode_security_struct *sec = selinux_inode(inode); + if (sec) { + sec->sid = ksu_devpts_sid; + } + } + + return 0; +} + +int __ksu_handle_devpts(struct inode *inode) +{ +#ifndef CONFIG_KSU_KPROBES_HOOK + if (!ksu_sucompat_non_kp) { + return 0; + } +#endif + return ksu_inline_handle_devpts(inode); +} + +// dead code, we are phasing out ksu_handle_devpts for LSM hooks. +int __maybe_unused ksu_handle_devpts(struct inode *inode) +{ + return 0; +} + #ifdef CONFIG_KSU_KPROBES_HOOK static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs) { @@ -222,6 +263,20 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) NULL); } +#ifdef MODULE +static struct kprobe *su_kps[4]; +static int pts_unix98_lookup_pre(struct kprobe *p, struct pt_regs *regs) +{ + struct inode *inode;) + struct file *file = (struct file *)PT_REGS_PARM2(regs); + inode = file->f_path.dentry->d_inode; + + return ksu_inline_handle_devpts(inode); +} +#else +static struct kprobe *su_kps[3]; +#endif + static struct kprobe *init_kprobe(const char *name, kprobe_pre_handler_t handler) { @@ -252,7 +307,6 @@ static void destroy_kprobe(struct kprobe **kp_ptr) *kp_ptr = NULL; } -static struct kprobe *su_kps[3]; #endif // sucompat: permited process can execute 'su' to gain root access. @@ -262,6 +316,9 @@ void ksu_sucompat_init() su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre); su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre); su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre); +#ifdef MODULE + su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre); +#endif #else ksu_sucompat_non_kp = true; pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat\n");