Since commit 6b1c66c9cca9 ("exec_state: relocate dumpable information"), copy_exec_state() can fail before rt_mutex_init_task() has reset the PI state that dup_task_struct() copied from the parent. If the allocation fails while the parent owns an rt_mutex with waiters, such as a contended PI futex, free_task() finds the parent's waiters in the child and warns with CONFIG_DEBUG_RT_MUTEXES=y: DEBUG_LOCKS_WARN_ON(!RB_EMPTY_ROOT(&task->pi_waiters.rb_root)) WARNING: kernel/locking/rtmutex_api.c:538 at rt_mutex_debug_task_free+0x7c/0xa0, CPU#0: repro/75 Call Trace: free_task+0x34/0x80 copy_process+0x5e6/0x2550 kernel_clone+0xd7/0x420 This also turns lock debugging off until reboot, or panics with panic_on_warn. Commit 08cacffeef8f ("ftrace: fork: Initialize function graph state before copy_exec_state()") fixed the same problem for the function graph stack. Move copy_exec_state() down to just before copy_creds(). That restores the order from before 6b1c66c9cca9, where copy_creds() was the first step that could fail. Fixes: 6b1c66c9cca9 ("exec_state: relocate dumpable information") Signed-off-by: Christian Aurich Zanettini Martins --- Notes: Reproduced in QEMU with failslab on the task_exec_state cache while the forking thread holds a PI futex another thread is waiting on. With this patch the fork just fails with -ENOMEM. Based on v7.4-rc1. kernel/fork.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index 8b108ed37152..fc12100e24d6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2147,9 +2147,6 @@ __latent_entropy struct task_struct *copy_process( * free the parent's ret_stack. */ ftrace_graph_init_task(p); - retval = copy_exec_state(clone_flags, p); - if (retval) - goto bad_fork_free; p->flags &= ~PF_KTHREAD; if (args->kthread) p->flags |= PF_KTHREAD; @@ -2177,6 +2174,13 @@ __latent_entropy struct task_struct *copy_process( #ifdef CONFIG_PROVE_LOCKING DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); #endif + /* + * First fallible op. Must run after rt_mutex_init_task(), so error + * paths never see the parent's PI waiters. + */ + retval = copy_exec_state(clone_flags, p); + if (retval) + goto bad_fork_free; retval = copy_creds(p, clone_flags); if (retval < 0) goto bad_fork_free; -- 2.43.0