aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coredump.c
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-08-15 14:11:45 -0400
committerSage Weil <sage@inktank.com>2013-08-15 14:11:45 -0400
commitee3e542fec6e69bc9fb668698889a37d93950ddf (patch)
treee74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/coredump.c
parentfe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff)
parentf1d6e17f540af37bb1891480143669ba7636c4cf (diff)
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/coredump.c')
-rw-r--r--fs/coredump.c121
1 files changed, 59 insertions, 62 deletions
diff --git a/fs/coredump.c b/fs/coredump.c
index dafafbafa731..72f816d6cad9 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -45,69 +45,79 @@
45#include <trace/events/sched.h> 45#include <trace/events/sched.h>
46 46
47int core_uses_pid; 47int core_uses_pid;
48char core_pattern[CORENAME_MAX_SIZE] = "core";
49unsigned int core_pipe_limit; 48unsigned int core_pipe_limit;
49char core_pattern[CORENAME_MAX_SIZE] = "core";
50static int core_name_size = CORENAME_MAX_SIZE;
50 51
51struct core_name { 52struct core_name {
52 char *corename; 53 char *corename;
53 int used, size; 54 int used, size;
54}; 55};
55static atomic_t call_count = ATOMIC_INIT(1);
56 56
57/* The maximal length of core_pattern is also specified in sysctl.c */ 57/* The maximal length of core_pattern is also specified in sysctl.c */
58 58
59static int expand_corename(struct core_name *cn) 59static int expand_corename(struct core_name *cn, int size)
60{ 60{
61 char *old_corename = cn->corename; 61 char *corename = krealloc(cn->corename, size, GFP_KERNEL);
62
63 cn->size = CORENAME_MAX_SIZE * atomic_inc_return(&call_count);
64 cn->corename = krealloc(old_corename, cn->size, GFP_KERNEL);
65 62
66 if (!cn->corename) { 63 if (!corename)
67 kfree(old_corename);
68 return -ENOMEM; 64 return -ENOMEM;
69 }
70 65
66 if (size > core_name_size) /* racy but harmless */
67 core_name_size = size;
68
69 cn->size = ksize(corename);
70 cn->corename = corename;
71 return 0; 71 return 0;
72} 72}
73 73
74static int cn_vprintf(struct core_name *cn, const char *fmt, va_list arg)
75{
76 int free, need;
77
78again:
79 free = cn->size - cn->used;
80 need = vsnprintf(cn->corename + cn->used, free, fmt, arg);
81 if (need < free) {
82 cn->used += need;
83 return 0;
84 }
85
86 if (!expand_corename(cn, cn->size + need - free + 1))
87 goto again;
88
89 return -ENOMEM;
90}
91
74static int cn_printf(struct core_name *cn, const char *fmt, ...) 92static int cn_printf(struct core_name *cn, const char *fmt, ...)
75{ 93{
76 char *cur;
77 int need;
78 int ret;
79 va_list arg; 94 va_list arg;
95 int ret;
80 96
81 va_start(arg, fmt); 97 va_start(arg, fmt);
82 need = vsnprintf(NULL, 0, fmt, arg); 98 ret = cn_vprintf(cn, fmt, arg);
83 va_end(arg); 99 va_end(arg);
84 100
85 if (likely(need < cn->size - cn->used - 1)) 101 return ret;
86 goto out_printf; 102}
87 103
88 ret = expand_corename(cn); 104static int cn_esc_printf(struct core_name *cn, const char *fmt, ...)
89 if (ret) 105{
90 goto expand_fail; 106 int cur = cn->used;
107 va_list arg;
108 int ret;
91 109
92out_printf:
93 cur = cn->corename + cn->used;
94 va_start(arg, fmt); 110 va_start(arg, fmt);
95 vsnprintf(cur, need + 1, fmt, arg); 111 ret = cn_vprintf(cn, fmt, arg);
96 va_end(arg); 112 va_end(arg);
97 cn->used += need;
98 return 0;
99 113
100expand_fail: 114 for (; cur < cn->used; ++cur) {
115 if (cn->corename[cur] == '/')
116 cn->corename[cur] = '!';
117 }
101 return ret; 118 return ret;
102} 119}
103 120
104static void cn_escape(char *str)
105{
106 for (; *str; str++)
107 if (*str == '/')
108 *str = '!';
109}
110
111static int cn_print_exe_file(struct core_name *cn) 121static int cn_print_exe_file(struct core_name *cn)
112{ 122{
113 struct file *exe_file; 123 struct file *exe_file;
@@ -115,12 +125,8 @@ static int cn_print_exe_file(struct core_name *cn)
115 int ret; 125 int ret;
116 126
117 exe_file = get_mm_exe_file(current->mm); 127 exe_file = get_mm_exe_file(current->mm);
118 if (!exe_file) { 128 if (!exe_file)
119 char *commstart = cn->corename + cn->used; 129 return cn_esc_printf(cn, "%s (path unknown)", current->comm);
120 ret = cn_printf(cn, "%s (path unknown)", current->comm);
121 cn_escape(commstart);
122 return ret;
123 }
124 130
125 pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY); 131 pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
126 if (!pathbuf) { 132 if (!pathbuf) {
@@ -134,9 +140,7 @@ static int cn_print_exe_file(struct core_name *cn)
134 goto free_buf; 140 goto free_buf;
135 } 141 }
136 142
137 cn_escape(path); 143 ret = cn_esc_printf(cn, "%s", path);
138
139 ret = cn_printf(cn, "%s", path);
140 144
141free_buf: 145free_buf:
142 kfree(pathbuf); 146 kfree(pathbuf);
@@ -157,19 +161,19 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
157 int pid_in_pattern = 0; 161 int pid_in_pattern = 0;
158 int err = 0; 162 int err = 0;
159 163
160 cn->size = CORENAME_MAX_SIZE * atomic_read(&call_count);
161 cn->corename = kmalloc(cn->size, GFP_KERNEL);
162 cn->used = 0; 164 cn->used = 0;
163 165 cn->corename = NULL;
164 if (!cn->corename) 166 if (expand_corename(cn, core_name_size))
165 return -ENOMEM; 167 return -ENOMEM;
168 cn->corename[0] = '\0';
169
170 if (ispipe)
171 ++pat_ptr;
166 172
167 /* Repeat as long as we have more pattern to process and more output 173 /* Repeat as long as we have more pattern to process and more output
168 space */ 174 space */
169 while (*pat_ptr) { 175 while (*pat_ptr) {
170 if (*pat_ptr != '%') { 176 if (*pat_ptr != '%') {
171 if (*pat_ptr == 0)
172 goto out;
173 err = cn_printf(cn, "%c", *pat_ptr++); 177 err = cn_printf(cn, "%c", *pat_ptr++);
174 } else { 178 } else {
175 switch (*++pat_ptr) { 179 switch (*++pat_ptr) {
@@ -210,22 +214,16 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
210 break; 214 break;
211 } 215 }
212 /* hostname */ 216 /* hostname */
213 case 'h': { 217 case 'h':
214 char *namestart = cn->corename + cn->used;
215 down_read(&uts_sem); 218 down_read(&uts_sem);
216 err = cn_printf(cn, "%s", 219 err = cn_esc_printf(cn, "%s",
217 utsname()->nodename); 220 utsname()->nodename);
218 up_read(&uts_sem); 221 up_read(&uts_sem);
219 cn_escape(namestart);
220 break; 222 break;
221 }
222 /* executable */ 223 /* executable */
223 case 'e': { 224 case 'e':
224 char *commstart = cn->corename + cn->used; 225 err = cn_esc_printf(cn, "%s", current->comm);
225 err = cn_printf(cn, "%s", current->comm);
226 cn_escape(commstart);
227 break; 226 break;
228 }
229 case 'E': 227 case 'E':
230 err = cn_print_exe_file(cn); 228 err = cn_print_exe_file(cn);
231 break; 229 break;
@@ -244,6 +242,7 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
244 return err; 242 return err;
245 } 243 }
246 244
245out:
247 /* Backward compatibility with core_uses_pid: 246 /* Backward compatibility with core_uses_pid:
248 * 247 *
249 * If core_pattern does not include a %p (as is the default) 248 * If core_pattern does not include a %p (as is the default)
@@ -254,7 +253,6 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
254 if (err) 253 if (err)
255 return err; 254 return err;
256 } 255 }
257out:
258 return ispipe; 256 return ispipe;
259} 257}
260 258
@@ -549,7 +547,7 @@ void do_coredump(siginfo_t *siginfo)
549 if (ispipe < 0) { 547 if (ispipe < 0) {
550 printk(KERN_WARNING "format_corename failed\n"); 548 printk(KERN_WARNING "format_corename failed\n");
551 printk(KERN_WARNING "Aborting core\n"); 549 printk(KERN_WARNING "Aborting core\n");
552 goto fail_corename; 550 goto fail_unlock;
553 } 551 }
554 552
555 if (cprm.limit == 1) { 553 if (cprm.limit == 1) {
@@ -584,7 +582,7 @@ void do_coredump(siginfo_t *siginfo)
584 goto fail_dropcount; 582 goto fail_dropcount;
585 } 583 }
586 584
587 helper_argv = argv_split(GFP_KERNEL, cn.corename+1, NULL); 585 helper_argv = argv_split(GFP_KERNEL, cn.corename, NULL);
588 if (!helper_argv) { 586 if (!helper_argv) {
589 printk(KERN_WARNING "%s failed to allocate memory\n", 587 printk(KERN_WARNING "%s failed to allocate memory\n",
590 __func__); 588 __func__);
@@ -601,7 +599,7 @@ void do_coredump(siginfo_t *siginfo)
601 599
602 argv_free(helper_argv); 600 argv_free(helper_argv);
603 if (retval) { 601 if (retval) {
604 printk(KERN_INFO "Core dump to %s pipe failed\n", 602 printk(KERN_INFO "Core dump to |%s pipe failed\n",
605 cn.corename); 603 cn.corename);
606 goto close_fail; 604 goto close_fail;
607 } 605 }
@@ -669,7 +667,6 @@ fail_dropcount:
669 atomic_dec(&core_dump_count); 667 atomic_dec(&core_dump_count);
670fail_unlock: 668fail_unlock:
671 kfree(cn.corename); 669 kfree(cn.corename);
672fail_corename:
673 coredump_finish(mm, core_dumped); 670 coredump_finish(mm, core_dumped);
674 revert_creds(old_cred); 671 revert_creds(old_cred);
675fail_creds: 672fail_creds: