diff options
author | Neil Horman <nhorman@tuxdriver.com> | 2007-10-16 23:26:35 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-17 08:42:50 -0700 |
commit | 74aadce986052f20088c2678f589ea0e8d3a4b59 (patch) | |
tree | e250181221f29e45e0b9d1e4175f569a66e639c4 | |
parent | 7dc0b22e3c54f1f4730354fef84a20f5944f6c5e (diff) |
core_pattern: allow passing of arguments to user mode helper when core_pattern is a pipe
A rewrite of my previous post for this enhancement. It uses jeremy's
split_argv/free_argv library functions to translate core_pattern into an argv
array to be passed to the user mode helper process. It also adds a
translation to format_corename such that the origional value of RLIMIT_CORE
can be passed to userspace as an argument.
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>
-rw-r--r-- | fs/exec.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/fs/exec.c b/fs/exec.c index 86c455447bc..6450157062e 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -29,6 +29,7 @@ #include <linux/stat.h> #include <linux/fcntl.h> #include <linux/smp_lock.h> +#include <linux/string.h> #include <linux/init.h> #include <linux/pagemap.h> #include <linux/highmem.h> @@ -1514,6 +1515,14 @@ static int format_corename(char *corename, const char *pattern, long signr) goto out; out_ptr += rc; break; + /* core limit size */ + case 'c': + rc = snprintf(out_ptr, out_end - out_ptr, + "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur); + if (rc > out_end - out_ptr) + goto out; + out_ptr += rc; + break; default: break; } @@ -1698,6 +1707,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) int flag = 0; int ispipe = 0; unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; + char **helper_argv = NULL; + int helper_argc = 0; + char *delimit; audit_core_dumps(signr); @@ -1746,14 +1758,18 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) * 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)) + if ((!ispipe) && (core_limit < binfmt->min_coredump)) goto fail_unlock; if (ispipe) { core_limit = RLIM_INFINITY; + helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); + /* Terminate the string before the first option */ + delimit = strchr(corename, ' '); + if (delimit) + *delimit = '\0'; /* SIGPIPE can happen, but it's just never processed */ - if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) { + if(call_usermodehelper_pipe(corename+1, helper_argv, NULL, &file)) { printk(KERN_INFO "Core dump to %s pipe failed\n", corename); goto fail_unlock; @@ -1788,6 +1804,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) close_fail: filp_close(file, NULL); fail_unlock: + if (helper_argv) + argv_free(helper_argv); + current->fsuid = fsuid; complete_all(&mm->core_done); fail: |