aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2007-10-17 02:26:34 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:50 -0400
commit7dc0b22e3c54f1f4730354fef84a20f5944f6c5e (patch)
tree8b281ed3315699eb0b21f00b5933b6222add5b5a
parent8e2b705649e294f43a8cd1ea79e4c594c0bd1d9d (diff)
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>
-rw-r--r--arch/mips/kernel/irixelf.c5
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c10
-rw-r--r--arch/x86/ia32/ia32_aout.c10
-rw-r--r--fs/binfmt_aout.c16
-rw-r--r--fs/binfmt_elf.c5
-rw-r--r--fs/binfmt_elf_fdpic.c5
-rw-r--r--fs/binfmt_flat.c4
-rw-r--r--fs/binfmt_som.c2
-rw-r--r--fs/exec.c19
-rw-r--r--include/linux/binfmts.h2
10 files changed, 39 insertions, 39 deletions
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 5a3fe43e3019..b997af713eb3 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -44,7 +44,7 @@
44static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs); 44static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
45static int load_irix_library(struct file *); 45static int load_irix_library(struct file *);
46static int irix_core_dump(long signr, struct pt_regs * regs, 46static int irix_core_dump(long signr, struct pt_regs * regs,
47 struct file *file); 47 struct file *file, unsigned long limit);
48 48
49static struct linux_binfmt irix_format = { 49static struct linux_binfmt irix_format = {
50 .module = THIS_MODULE, 50 .module = THIS_MODULE,
@@ -1091,7 +1091,7 @@ end_coredump:
1091 * and then they are actually written out. If we run out of core limit 1091 * and then they are actually written out. If we run out of core limit
1092 * we just truncate. 1092 * we just truncate.
1093 */ 1093 */
1094static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) 1094static int irix_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
1095{ 1095{
1096 int has_dumped = 0; 1096 int has_dumped = 0;
1097 mm_segment_t fs; 1097 mm_segment_t fs;
@@ -1101,7 +1101,6 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
1101 struct vm_area_struct *vma; 1101 struct vm_area_struct *vma;
1102 struct elfhdr elf; 1102 struct elfhdr elf;
1103 off_t offset = 0, dataoff; 1103 off_t offset = 0, dataoff;
1104 int limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1105 int numnote = 3; 1104 int numnote = 3;
1106 struct memelfnote notes[3]; 1105 struct memelfnote notes[3];
1107 struct elf_prstatus prstatus; /* NT_PRSTATUS */ 1106 struct elf_prstatus prstatus; /* NT_PRSTATUS */
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index c8acbeab49b4..92c1b36a2e16 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -35,7 +35,7 @@
35 35
36static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs); 36static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
37static int load_aout32_library(struct file*); 37static int load_aout32_library(struct file*);
38static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file); 38static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
39 39
40static struct linux_binfmt aout32_format = { 40static struct linux_binfmt aout32_format = {
41 .module = THIS_MODULE, 41 .module = THIS_MODULE,
@@ -86,7 +86,7 @@ if (file->f_op->llseek) { \
86 * dumping of the process results in another error.. 86 * dumping of the process results in another error..
87 */ 87 */
88 88
89static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file) 89static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
90{ 90{
91 mm_segment_t fs; 91 mm_segment_t fs;
92 int has_dumped = 0; 92 int has_dumped = 0;
@@ -105,13 +105,11 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
105 105
106/* If the size of the dump file exceeds the rlimit, then see what would happen 106/* If the size of the dump file exceeds the rlimit, then see what would happen
107 if we wrote the stack, but not the data area. */ 107 if we wrote the stack, but not the data area. */
108 if ((dump.u_dsize+dump.u_ssize) > 108 if (dump.u_dsize + dump.u_ssize > limit)
109 current->signal->rlim[RLIMIT_CORE].rlim_cur)
110 dump.u_dsize = 0; 109 dump.u_dsize = 0;
111 110
112/* Make sure we have enough room to write the stack and data areas. */ 111/* Make sure we have enough room to write the stack and data areas. */
113 if ((dump.u_ssize) > 112 if (dump.u_ssize > limit)
114 current->signal->rlim[RLIMIT_CORE].rlim_cur)
115 dump.u_ssize = 0; 113 dump.u_ssize = 0;
116 114
117/* make sure we actually have a data and stack area to dump */ 115/* make sure we actually have a data and stack area to dump */
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 08781370256d..7cf1c29bf90e 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -40,7 +40,7 @@ static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
40static int load_aout_library(struct file*); 40static int load_aout_library(struct file*);
41 41
42#ifdef CORE_DUMP 42#ifdef CORE_DUMP
43static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file); 43static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
44 44
45/* 45/*
46 * fill in the user structure for a core dump.. 46 * fill in the user structure for a core dump..
@@ -148,7 +148,7 @@ if (file->f_op->llseek) { \
148 * dumping of the process results in another error.. 148 * dumping of the process results in another error..
149 */ 149 */
150 150
151static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file) 151static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
152{ 152{
153 mm_segment_t fs; 153 mm_segment_t fs;
154 int has_dumped = 0; 154 int has_dumped = 0;
@@ -168,13 +168,11 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
168 168
169/* If the size of the dump file exceeds the rlimit, then see what would happen 169/* If the size of the dump file exceeds the rlimit, then see what would happen
170 if we wrote the stack, but not the data area. */ 170 if we wrote the stack, but not the data area. */
171 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE > 171 if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit)
172 current->signal->rlim[RLIMIT_CORE].rlim_cur)
173 dump.u_dsize = 0; 172 dump.u_dsize = 0;
174 173
175/* Make sure we have enough room to write the stack and data areas. */ 174/* Make sure we have enough room to write the stack and data areas. */
176 if ((dump.u_ssize+1) * PAGE_SIZE > 175 if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
177 current->signal->rlim[RLIMIT_CORE].rlim_cur)
178 dump.u_ssize = 0; 176 dump.u_ssize = 0;
179 177
180/* make sure we actually have a data and stack area to dump */ 178/* make sure we actually have a data and stack area to dump */
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 813a887cd2b3..e176d195e7e5 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -31,7 +31,7 @@
31 31
32static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); 32static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
33static int load_aout_library(struct file*); 33static int load_aout_library(struct file*);
34static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file); 34static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
35 35
36static struct linux_binfmt aout_format = { 36static struct linux_binfmt aout_format = {
37 .module = THIS_MODULE, 37 .module = THIS_MODULE,
@@ -88,7 +88,7 @@ if (file->f_op->llseek) { \
88 * dumping of the process results in another error.. 88 * dumping of the process results in another error..
89 */ 89 */
90 90
91static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file) 91static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
92{ 92{
93 mm_segment_t fs; 93 mm_segment_t fs;
94 int has_dumped = 0; 94 int has_dumped = 0;
@@ -123,23 +123,19 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
123/* If the size of the dump file exceeds the rlimit, then see what would happen 123/* If the size of the dump file exceeds the rlimit, then see what would happen
124 if we wrote the stack, but not the data area. */ 124 if we wrote the stack, but not the data area. */
125#ifdef __sparc__ 125#ifdef __sparc__
126 if ((dump.u_dsize+dump.u_ssize) > 126 if ((dump.u_dsize + dump.u_ssize) > limit)
127 current->signal->rlim[RLIMIT_CORE].rlim_cur)
128 dump.u_dsize = 0; 127 dump.u_dsize = 0;
129#else 128#else
130 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE > 129 if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
131 current->signal->rlim[RLIMIT_CORE].rlim_cur)
132 dump.u_dsize = 0; 130 dump.u_dsize = 0;
133#endif 131#endif
134 132
135/* Make sure we have enough room to write the stack and data areas. */ 133/* Make sure we have enough room to write the stack and data areas. */
136#ifdef __sparc__ 134#ifdef __sparc__
137 if ((dump.u_ssize) > 135 if (dump.u_ssize > limit)
138 current->signal->rlim[RLIMIT_CORE].rlim_cur)
139 dump.u_ssize = 0; 136 dump.u_ssize = 0;
140#else 137#else
141 if ((dump.u_ssize+1) * PAGE_SIZE > 138 if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
142 current->signal->rlim[RLIMIT_CORE].rlim_cur)
143 dump.u_ssize = 0; 139 dump.u_ssize = 0;
144#endif 140#endif
145 141
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 2f31c4c3fd48..3dc6a123fa10 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -52,7 +52,7 @@ static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, i
52 * don't even try. 52 * don't even try.
53 */ 53 */
54#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) 54#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
55static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file); 55static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
56#else 56#else
57#define elf_core_dump NULL 57#define elf_core_dump NULL
58#endif 58#endif
@@ -1488,7 +1488,7 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
1488 * and then they are actually written out. If we run out of core limit 1488 * and then they are actually written out. If we run out of core limit
1489 * we just truncate. 1489 * we just truncate.
1490 */ 1490 */
1491static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) 1491static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
1492{ 1492{
1493#define NUM_NOTES 6 1493#define NUM_NOTES 6
1494 int has_dumped = 0; 1494 int has_dumped = 0;
@@ -1499,7 +1499,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1499 struct vm_area_struct *vma, *gate_vma; 1499 struct vm_area_struct *vma, *gate_vma;
1500 struct elfhdr *elf = NULL; 1500 struct elfhdr *elf = NULL;
1501 loff_t offset = 0, dataoff, foffset; 1501 loff_t offset = 0, dataoff, foffset;
1502 unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1503 int numnote; 1502 int numnote;
1504 struct memelfnote *notes = NULL; 1503 struct memelfnote *notes = NULL;
1505 struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ 1504 struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index faae02189598..033861c6b8f1 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -75,7 +75,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
75 struct file *, struct mm_struct *); 75 struct file *, struct mm_struct *);
76 76
77#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) 77#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
78static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *); 78static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *, unsigned long limit);
79#endif 79#endif
80 80
81static struct linux_binfmt elf_fdpic_format = { 81static struct linux_binfmt elf_fdpic_format = {
@@ -1552,7 +1552,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
1552 * we just truncate. 1552 * we just truncate.
1553 */ 1553 */
1554static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, 1554static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
1555 struct file *file) 1555 struct file *file, unsigned long limit)
1556{ 1556{
1557#define NUM_NOTES 6 1557#define NUM_NOTES 6
1558 int has_dumped = 0; 1558 int has_dumped = 0;
@@ -1563,7 +1563,6 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
1563 struct vm_area_struct *vma; 1563 struct vm_area_struct *vma;
1564 struct elfhdr *elf = NULL; 1564 struct elfhdr *elf = NULL;
1565 loff_t offset = 0, dataoff; 1565 loff_t offset = 0, dataoff;
1566 unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1567 int numnote; 1566 int numnote;
1568 struct memelfnote *notes = NULL; 1567 struct memelfnote *notes = NULL;
1569 struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ 1568 struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index fcb3405bb14e..265fac868067 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -75,7 +75,7 @@ static int load_flat_shared_library(int id, struct lib_info *p);
75#endif 75#endif
76 76
77static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs); 77static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
78static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file); 78static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
79 79
80static struct linux_binfmt flat_format = { 80static struct linux_binfmt flat_format = {
81 .module = THIS_MODULE, 81 .module = THIS_MODULE,
@@ -90,7 +90,7 @@ static struct linux_binfmt flat_format = {
90 * Currently only a stub-function. 90 * Currently only a stub-function.
91 */ 91 */
92 92
93static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file) 93static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
94{ 94{
95 printk("Process %s:%d received signr %d and should have core dumped\n", 95 printk("Process %s:%d received signr %d and should have core dumped\n",
96 current->comm, current->pid, (int) signr); 96 current->comm, current->pid, (int) signr);
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 5bcdaaf4eae0..9208c41209f9 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -44,7 +44,7 @@ static int load_som_library(struct file *);
44 * don't even try. 44 * don't even try.
45 */ 45 */
46#if 0 46#if 0
47static int som_core_dump(long signr, struct pt_regs * regs); 47static int som_core_dump(long signr, struct pt_regs *regs, unsigned long limit);
48#else 48#else
49#define som_core_dump NULL 49#define som_core_dump NULL
50#endif 50#endif
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)
1697 int fsuid = current->fsuid; 1697 int fsuid = current->fsuid;
1698 int flag = 0; 1698 int flag = 0;
1699 int ispipe = 0; 1699 int ispipe = 0;
1700 unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
1700 1701
1701 audit_core_dumps(signr); 1702 audit_core_dumps(signr);
1702 1703
@@ -1730,9 +1731,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1730 */ 1731 */
1731 clear_thread_flag(TIF_SIGPENDING); 1732 clear_thread_flag(TIF_SIGPENDING);
1732 1733
1733 if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
1734 goto fail_unlock;
1735
1736 /* 1734 /*
1737 * lock_kernel() because format_corename() is controlled by sysctl, which 1735 * lock_kernel() because format_corename() is controlled by sysctl, which
1738 * uses lock_kernel() 1736 * uses lock_kernel()
@@ -1740,7 +1738,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1740 lock_kernel(); 1738 lock_kernel();
1741 ispipe = format_corename(corename, core_pattern, signr); 1739 ispipe = format_corename(corename, core_pattern, signr);
1742 unlock_kernel(); 1740 unlock_kernel();
1741 /*
1742 * Don't bother to check the RLIMIT_CORE value if core_pattern points
1743 * to a pipe. Since we're not writing directly to the filesystem
1744 * RLIMIT_CORE doesn't really apply, as no actual core file will be
1745 * created unless the pipe reader choses to write out the core file
1746 * at which point file size limits and permissions will be imposed
1747 * as it does with any other process
1748 */
1749 if ((!ispipe) &&
1750 (core_limit < binfmt->min_coredump))
1751 goto fail_unlock;
1752
1743 if (ispipe) { 1753 if (ispipe) {
1754 core_limit = RLIM_INFINITY;
1744 /* SIGPIPE can happen, but it's just never processed */ 1755 /* SIGPIPE can happen, but it's just never processed */
1745 if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) { 1756 if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
1746 printk(KERN_INFO "Core dump to %s pipe failed\n", 1757 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)
1770 if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0) 1781 if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
1771 goto close_fail; 1782 goto close_fail;
1772 1783
1773 retval = binfmt->core_dump(signr, regs, file); 1784 retval = binfmt->core_dump(signr, regs, file, core_limit);
1774 1785
1775 if (retval) 1786 if (retval)
1776 current->signal->group_exit_code |= 0x80; 1787 current->signal->group_exit_code |= 0x80;
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 63d54366e0e5..3a6512f8ec94 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -67,7 +67,7 @@ struct linux_binfmt {
67 struct module *module; 67 struct module *module;
68 int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); 68 int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
69 int (*load_shlib)(struct file *); 69 int (*load_shlib)(struct file *);
70 int (*core_dump)(long signr, struct pt_regs * regs, struct file * file); 70 int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
71 unsigned long min_coredump; /* minimal dump size */ 71 unsigned long min_coredump; /* minimal dump size */
72 int hasvdso; 72 int hasvdso;
73}; 73};