diff options
-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 86c455447bc8..6450157062ea 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: |