diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 913867a579c1..bdf6d97ed8f7 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -106,14 +106,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); @@ -147,21 +171,15 @@ void escape_to_root(void) memcpy(&cred->cap_ambient, &profile->capabilities.effective, 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); }