summaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2007-10-17 08:26:34 +0200
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 17:42:50 +0200
commit7dc0b22e3c54f1f4730354fef84a20f5944f6c5e (patch)
tree8b281ed3315699eb0b21f00b5933b6222add5b5a /fs/exec.c
parentargv_split: allow argv_split to handle NULL pointer in argcp parameter gracef... (diff)
downloadlinux-7dc0b22e3c54f1f4730354fef84a20f5944f6c5e.tar.xz
linux-7dc0b22e3c54f1f4730354fef84a20f5944f6c5e.zip
core_pattern: ignore RLIMIT_CORE if core_pattern is a pipe
For some time /proc/sys/kernel/core_pattern has been able to set its output destination as a pipe, allowing a user space helper to receive and intellegently process a core. This infrastructure however has some shortcommings which can be enhanced. Specifically: 1) The coredump code in the kernel should ignore RLIMIT_CORE limitation when core_pattern is a pipe, since file system resources are not being consumed in this case, unless the user application wishes to save the core, at which point the app is restricted by usual file system limits and restrictions. 2) The core_pattern code should be able to parse and pass options to the user space helper as an argv array. The real core limit of the uid of the crashing proces should also be passable to the user space helper (since it is overridden to zero when called). 3) Some miscellaneous bugs need to be cleaned up (specifically the recognition of a recursive core dump, should the user mode helper itself crash. Also, the core dump code in the kernel should not wait for the user mode helper to exit, since the same context is responsible for writing to the pipe, and a read of the pipe by the user mode helper will result in a deadlock. This patch: Remove the check of RLIMIT_CORE if core_pattern is a pipe. In the event that core_pattern is a pipe, the entire core will be fed to the user mode helper. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Cc: <martin.pitt@ubuntu.com> Cc: <wwoods@redhat.com> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 550ae9b22f8d..86c455447bc8 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1697,6 +1697,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
int fsuid = current->fsuid;
int flag = 0;
int ispipe = 0;
+ unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
audit_core_dumps(signr);
@@ -1730,9 +1731,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
*/
clear_thread_flag(TIF_SIGPENDING);
- if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
- goto fail_unlock;
-
/*
* lock_kernel() because format_corename() is controlled by sysctl, which
* uses lock_kernel()
@@ -1740,7 +1738,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
lock_kernel();
ispipe = format_corename(corename, core_pattern, signr);
unlock_kernel();
+ /*
+ * Don't bother to check the RLIMIT_CORE value if core_pattern points
+ * to a pipe. Since we're not writing directly to the filesystem
+ * RLIMIT_CORE doesn't really apply, as no actual core file will be
+ * created unless the pipe reader choses to write out the core file
+ * at which point file size limits and permissions will be imposed
+ * as it does with any other process
+ */
+ if ((!ispipe) &&
+ (core_limit < binfmt->min_coredump))
+ goto fail_unlock;
+
if (ispipe) {
+ core_limit = RLIM_INFINITY;
/* SIGPIPE can happen, but it's just never processed */
if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
printk(KERN_INFO "Core dump to %s pipe failed\n",
@@ -1770,7 +1781,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
goto close_fail;
- retval = binfmt->core_dump(signr, regs, file);
+ retval = binfmt->core_dump(signr, regs, file, core_limit);
if (retval)
current->signal->group_exit_code |= 0x80;