aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coredump.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2013-04-30 18:28:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 20:04:06 -0400
commitacdedd99b0f3bff9b4bb2103a6b1268c03d1f963 (patch)
treebfacbb825c6024a0374db0a6a38a222581b15083 /fs/coredump.c
parent6cd8f0acae3420afce37bf51a9ff8c2c20342af5 (diff)
coredump: sanitize the setting of signal->group_exit_code
Now that the coredumping process can be SIGKILL'ed, the setting of ->group_exit_code in do_coredump() can race with complete_signal() and SIGKILL or 0x80 can be "lost", or wait(status) can report status == SIGKILL | 0x80. But the main problem is that it is not clear to me what should we do if binfmt->core_dump() succeeds but SIGKILL was sent, that is why this patch comes as a separate change. This patch adds 0x80 if ->core_dump() succeeds and the process was not killed. But perhaps we can (should?) re-set ->group_exit_code changed by SIGKILL back to "siginfo->si_signo |= 0x80" in case when core_dumped == T. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Tested-by: Mandeep Singh Baines <msb@chromium.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Neil Horman <nhorman@redhat.com> Cc: "Rafael J. Wysocki" <rjw@sisk.pl> Cc: Roland McGrath <roland@hack.frob.com> Cc: Tejun Heo <tj@kernel.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/coredump.c')
-rw-r--r--fs/coredump.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/fs/coredump.c b/fs/coredump.c
index 6fea59043532..acc4448c28e7 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -390,12 +390,14 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
390 return core_waiters; 390 return core_waiters;
391} 391}
392 392
393static void coredump_finish(struct mm_struct *mm) 393static void coredump_finish(struct mm_struct *mm, bool core_dumped)
394{ 394{
395 struct core_thread *curr, *next; 395 struct core_thread *curr, *next;
396 struct task_struct *task; 396 struct task_struct *task;
397 397
398 spin_lock_irq(&current->sighand->siglock); 398 spin_lock_irq(&current->sighand->siglock);
399 if (core_dumped && !__fatal_signal_pending(current))
400 current->signal->group_exit_code |= 0x80;
399 current->signal->group_exit_task = NULL; 401 current->signal->group_exit_task = NULL;
400 current->signal->flags = SIGNAL_GROUP_EXIT; 402 current->signal->flags = SIGNAL_GROUP_EXIT;
401 spin_unlock_irq(&current->sighand->siglock); 403 spin_unlock_irq(&current->sighand->siglock);
@@ -480,6 +482,7 @@ void do_coredump(siginfo_t *siginfo)
480 int ispipe; 482 int ispipe;
481 struct files_struct *displaced; 483 struct files_struct *displaced;
482 bool need_nonrelative = false; 484 bool need_nonrelative = false;
485 bool core_dumped = false;
483 static atomic_t core_dump_count = ATOMIC_INIT(0); 486 static atomic_t core_dump_count = ATOMIC_INIT(0);
484 struct coredump_params cprm = { 487 struct coredump_params cprm = {
485 .siginfo = siginfo, 488 .siginfo = siginfo,
@@ -638,9 +641,7 @@ void do_coredump(siginfo_t *siginfo)
638 goto close_fail; 641 goto close_fail;
639 if (displaced) 642 if (displaced)
640 put_files_struct(displaced); 643 put_files_struct(displaced);
641 retval = binfmt->core_dump(&cprm); 644 core_dumped = binfmt->core_dump(&cprm);
642 if (retval)
643 current->signal->group_exit_code |= 0x80;
644 645
645 if (ispipe && core_pipe_limit) 646 if (ispipe && core_pipe_limit)
646 wait_for_dump_helpers(cprm.file); 647 wait_for_dump_helpers(cprm.file);
@@ -653,7 +654,7 @@ fail_dropcount:
653fail_unlock: 654fail_unlock:
654 kfree(cn.corename); 655 kfree(cn.corename);
655fail_corename: 656fail_corename:
656 coredump_finish(mm); 657 coredump_finish(mm, core_dumped);
657 revert_creds(old_cred); 658 revert_creds(old_cred);
658fail_creds: 659fail_creds:
659 put_cred(cred); 660 put_cred(cred);