kernel: Resolved potential deadlock issues arising from operations not being performed within locks.

This commit is contained in:
ShirkNeko
2025-11-14 11:55:06 +08:00
parent 9203006028
commit d3461a6421
3 changed files with 18 additions and 32 deletions

View File

@@ -66,10 +66,9 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
put_group_info(group_info); put_group_info(group_info);
} }
void disable_seccomp(struct task_struct *tsk) void disable_seccomp(void)
{ {
assert_spin_locked(&tsk->sighand->siglock); assert_spin_locked(&current->sighand->siglock);
// disable seccomp // disable seccomp
#if defined(CONFIG_GENERIC_ENTRY) && \ #if defined(CONFIG_GENERIC_ENTRY) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
@@ -79,20 +78,10 @@ void disable_seccomp(struct task_struct *tsk)
#endif #endif
#ifdef CONFIG_SECCOMP #ifdef CONFIG_SECCOMP
tsk->seccomp.mode = 0; current->seccomp.mode = 0;
if (tsk->seccomp.filter) { current->seccomp.filter = NULL;
// 5.9+ have filter_count and use seccomp_filter_release atomic_set(&current->seccomp.filter_count, 0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
seccomp_filter_release(tsk);
atomic_set(&tsk->seccomp.filter_count, 0);
#else #else
// for 6.11+ kernel support?
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
put_seccomp_filter(tsk);
#endif
tsk->seccomp.filter = NULL;
#endif
}
#endif #endif
} }
@@ -152,7 +141,7 @@ void escape_with_root_profile(void)
// Refer to kernel/seccomp.c: seccomp_set_mode_strict // Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation. // When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
disable_seccomp(current); disable_seccomp();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
setup_selinux(profile->selinux_domain); setup_selinux(profile->selinux_domain);
@@ -202,23 +191,19 @@ static int __manual_su_handle_devpts(struct inode *inode)
static void disable_seccomp_for_task(struct task_struct *tsk) static void disable_seccomp_for_task(struct task_struct *tsk)
{ {
if (!tsk->seccomp.filter && tsk->seccomp.mode == SECCOMP_MODE_DISABLED) assert_spin_locked(&tsk->sighand->siglock);
return;
if (WARN_ON(!spin_is_locked(&tsk->sighand->siglock)))
return;
#ifdef CONFIG_SECCOMP #ifdef CONFIG_SECCOMP
tsk->seccomp.mode = 0; if (tsk->seccomp.mode == SECCOMP_MODE_DISABLED && !tsk->seccomp.filter)
return;
#endif
clear_tsk_thread_flag(tsk, TIF_SECCOMP);
#ifdef CONFIG_SECCOMP
tsk->seccomp.mode = SECCOMP_MODE_DISABLED;
if (tsk->seccomp.filter) { if (tsk->seccomp.filter) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
seccomp_filter_release(tsk); seccomp_filter_release(tsk);
atomic_set(&tsk->seccomp.filter_count, 0);
#else #else
// for 6.11+ kernel support?
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
put_seccomp_filter(tsk); put_seccomp_filter(tsk);
#endif
tsk->seccomp.filter = NULL; tsk->seccomp.filter = NULL;
#endif #endif
} }
@@ -229,6 +214,7 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
{ {
struct cred *newcreds; struct cred *newcreds;
struct task_struct *target_task; struct task_struct *target_task;
unsigned long flags;
struct task_struct *p = current; struct task_struct *p = current;
struct task_struct *t; struct task_struct *t;
@@ -292,9 +278,9 @@ void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid)
task_unlock(target_task); task_unlock(target_task);
if (target_task->sighand) { if (target_task->sighand) {
spin_lock_irq(&target_task->sighand->siglock); spin_lock_irqsave(&target_task->sighand->siglock, flags);
disable_seccomp_for_task(target_task); disable_seccomp_for_task(target_task);
spin_unlock_irq(&target_task->sighand->siglock); spin_unlock_irqrestore(&target_task->sighand->siglock, flags);
} }
setup_selinux(profile->selinux_domain); setup_selinux(profile->selinux_domain);

View File

@@ -65,6 +65,6 @@ void escape_with_root_profile(void);
void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid); void escape_to_root_for_cmd_su(uid_t target_uid, pid_t target_pid);
void disable_seccomp(struct task_struct *tsk); void disable_seccomp(void);
#endif #endif

View File

@@ -153,7 +153,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
#else #else
if (ksu_is_allow_uid_for_current(new_uid)) { if (ksu_is_allow_uid_for_current(new_uid)) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
disable_seccomp(current); disable_seccomp();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (ksu_get_manager_uid() == new_uid) { if (ksu_get_manager_uid() == new_uid) {