From b18c39e9117c2f3602d961467762aef673f48835 Mon Sep 17 00:00:00 2001 From: SsageParuders <75780727+SsageParuders@users.noreply.github.com> Date: Sat, 28 Dec 2024 13:33:21 +0800 Subject: [PATCH] Improve seccomp disable && Add locking to protect cred modifications in escape_to_root (#2320) - When disabling Seccomp, ensure that current->sighand->siglock is held during the operation. - Locking to ensure safe access and modification of the `cred` structure within the `escape_to_root` function. --- I think this issue described in #2236 may have been caused by concurrent read-write access without proper locking. --------- Signed-off-by: SsageParuders Signed-off-by: SsageParuders " --- kernel/core_hook.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 93be8bad..ec3b3ebd 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -110,14 +110,38 @@ static void setup_groups(struct root_profile *profile, struct cred *cred) set_groups(cred, group_info); } +static void disable_seccomp() +{ + assert_spin_locked(¤t->sighand->siglock); + // disable seccomp +#if defined(CONFIG_GENERIC_ENTRY) && \ + LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) + current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP; +#else + current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP); +#endif + +#ifdef CONFIG_SECCOMP + current->seccomp.mode = 0; + current->seccomp.filter = NULL; +#else +#endif +} + void escape_to_root(void) { struct cred *cred; - cred = (struct cred *)__task_cred(current); + rcu_read_lock(); + + do { + cred = (struct cred *)__task_cred((current)); + BUG_ON(!cred); + } while (!get_cred_rcu(cred)); if (cred->euid.val == 0) { pr_warn("Already root, don't escape!\n"); + rcu_read_unlock(); return; } struct root_profile *profile = ksu_get_root_profile(cred->uid.val); @@ -155,21 +179,15 @@ void escape_to_root(void) memset(&cred->cap_ambient, 0, sizeof(cred->cap_ambient)); - // disable seccomp -#if defined(CONFIG_GENERIC_ENTRY) && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) - current_thread_info()->syscall_work &= ~SYSCALL_WORK_SECCOMP; -#else - current_thread_info()->flags &= ~(TIF_SECCOMP | _TIF_SECCOMP); -#endif + setup_groups(profile, cred); -#ifdef CONFIG_SECCOMP - current->seccomp.mode = 0; - current->seccomp.filter = NULL; -#else -#endif + rcu_read_unlock(); - setup_groups(profile, cred); + // Refer to kernel/seccomp.c: seccomp_set_mode_strict + // When disabling Seccomp, ensure that current->sighand->siglock is held during the operation. + spin_lock_irq(¤t->sighand->siglock); + disable_seccomp(); + spin_unlock_irq(¤t->sighand->siglock); setup_selinux(profile->selinux_domain); }