From: Oleg Nesterov Date: Tue, 26 May 2026 14:42:11 +0000 (+0200) Subject: mm/migrate: find_mm_struct: fix race between security checks and suid exec X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=13f77972b94c51f6e5b94d672025601363440a94;p=thirdparty%2Fkernel%2Flinux.git mm/migrate: find_mm_struct: fix race between security checks and suid exec The target task can execute a setuid binary between ptrace_may_access() and get_task_mm(). Protect this critical section with exec_update_lock. I don't think cpuset_mems_allowed(task) should be called under exec_update_lock, but this patch just tries to add the minimal fix. Perhaps we can later add a common helper which can be used by find_mm_struct() and kernel_migrate_pages(). Link: https://lore.kernel.org/ahWxQ3JxdR5ff2qf@redhat.com Signed-off-by: Oleg Nesterov Reviewed-by: Gregory Price Cc: Alistair Popple Cc: Byungchul Park Cc: David Hildenbrand Cc: "Huang, Ying" Cc: Jann Horn Cc: Joshua Hahn Cc: Kees Cook Cc: Matthew Brost Cc: Rakie Kim Cc: Ying Huang Cc: Zi Yan Signed-off-by: Andrew Morton --- diff --git a/mm/migrate.c b/mm/migrate.c index d8090cdda4f9..d9b23909d716 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -2555,24 +2555,29 @@ static struct mm_struct *find_mm_struct(pid_t pid, nodemask_t *mem_nodes) } task = find_get_task_by_vpid(pid); - if (!task) { + if (!task) return ERR_PTR(-ESRCH); - } + if (down_read_killable(&task->signal->exec_update_lock)) { + mm = ERR_PTR(-EINTR); + goto out; + } /* * Check if this process has the right to modify the specified * process. Use the regular "ptrace_may_access()" checks. */ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) { mm = ERR_PTR(-EPERM); - goto out; + goto unlock; } mm = ERR_PTR(security_task_movememory(task)); if (IS_ERR(mm)) - goto out; + goto unlock; *mem_nodes = cpuset_mems_allowed(task); mm = get_task_mm(task); +unlock: + up_read(&task->signal->exec_update_lock); out: put_task_struct(task); if (!mm)