diff options
author | Oleg Nesterov <oleg@redhat.com> | 2015-10-22 16:32:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-10-23 04:55:10 -0400 |
commit | 5211613978cb7353a3237e4372958c0e7514683f (patch) | |
tree | 01fae404b1b576e032245ef68ee50f0a92ea8090 /kernel/kmod.c | |
parent | 8a70dd2669200ce83255ed8c5ebef7e59f9e8707 (diff) |
kmod: don't run async usermode helper as a child of kworker thread
call_usermodehelper_exec_sync() does fork() + wait() with "unignored"
SIGCHLD. What we have missed is that this worker thread can have other
children previously forked by call_usermodehelper_exec_work() without
UMH_WAIT_PROC. If such a child exits in between it becomes a zombie
because auto-reaping only works if SIGCHLD is ignored, and nobody can
reap it (unless/until this worker thread exits too).
Change the !UMH_WAIT_PROC case to use CLONE_PARENT.
Note: this is only first step. All PF_KTHREAD tasks, even created by
kernel_thread() should have ->parent == kthreadd by default.
Fixes: bb304a5c6fc63d8506c ("kmod: handle UMH_WAIT_PROC from system unbound workqueue")
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kmod.c')
-rw-r--r-- | kernel/kmod.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c index da98d0593de2..0277d1216f80 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -327,9 +327,13 @@ static void call_usermodehelper_exec_work(struct work_struct *work) | |||
327 | call_usermodehelper_exec_sync(sub_info); | 327 | call_usermodehelper_exec_sync(sub_info); |
328 | } else { | 328 | } else { |
329 | pid_t pid; | 329 | pid_t pid; |
330 | 330 | /* | |
331 | * Use CLONE_PARENT to reparent it to kthreadd; we do not | ||
332 | * want to pollute current->children, and we need a parent | ||
333 | * that always ignores SIGCHLD to ensure auto-reaping. | ||
334 | */ | ||
331 | pid = kernel_thread(call_usermodehelper_exec_async, sub_info, | 335 | pid = kernel_thread(call_usermodehelper_exec_async, sub_info, |
332 | SIGCHLD); | 336 | CLONE_PARENT | SIGCHLD); |
333 | if (pid < 0) { | 337 | if (pid < 0) { |
334 | sub_info->retval = pid; | 338 | sub_info->retval = pid; |
335 | umh_complete(sub_info); | 339 | umh_complete(sub_info); |