aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Gang <gang.chen@asianux.com>2013-04-15 01:34:43 -0400
committerRusty Russell <rusty@rustcorp.com.au>2013-04-15 01:47:26 -0400
commite3f26752f0f8a6aade580115e1e68bcb1a4bc040 (patch)
tree04e818066d7d0faa64abfe55b4841da984f3812f
parent07c449bbc6aa514098c4f12c7b04180cec2417c6 (diff)
kernel: kallsyms: memory override issue, need check destination buffer length
We don't export any symbols > 128 characters, but if we did then kallsyms_expand_symbol() would overflow the buffer handed to it. So we need check destination buffer length when copying. the related test: if we define an EXPORT function which name more than 128. will panic when call kallsyms_lookup_name by init_kprobes on booting. after check the length (provide this patch), it is ok. Implementaion: add additional destination buffer length parameter (maxlen) if uncompressed string is too long (>= maxlen), it will be truncated. not check the parameters whether valid, since it is a static function. Signed-off-by: Chen Gang <gang.chen@asianux.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--kernel/kallsyms.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 2169feeba529..3127ad52cdb2 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -84,9 +84,11 @@ static int is_ksym_addr(unsigned long addr)
84 84
85/* 85/*
86 * Expand a compressed symbol data into the resulting uncompressed string, 86 * Expand a compressed symbol data into the resulting uncompressed string,
87 * if uncompressed string is too long (>= maxlen), it will be truncated,
87 * given the offset to where the symbol is in the compressed stream. 88 * given the offset to where the symbol is in the compressed stream.
88 */ 89 */
89static unsigned int kallsyms_expand_symbol(unsigned int off, char *result) 90static unsigned int kallsyms_expand_symbol(unsigned int off,
91 char *result, size_t maxlen)
90{ 92{
91 int len, skipped_first = 0; 93 int len, skipped_first = 0;
92 const u8 *tptr, *data; 94 const u8 *tptr, *data;
@@ -113,15 +115,20 @@ static unsigned int kallsyms_expand_symbol(unsigned int off, char *result)
113 115
114 while (*tptr) { 116 while (*tptr) {
115 if (skipped_first) { 117 if (skipped_first) {
118 if (maxlen <= 1)
119 goto tail;
116 *result = *tptr; 120 *result = *tptr;
117 result++; 121 result++;
122 maxlen--;
118 } else 123 } else
119 skipped_first = 1; 124 skipped_first = 1;
120 tptr++; 125 tptr++;
121 } 126 }
122 } 127 }
123 128
124 *result = '\0'; 129tail:
130 if (maxlen)
131 *result = '\0';
125 132
126 /* Return to offset to the next symbol. */ 133 /* Return to offset to the next symbol. */
127 return off; 134 return off;
@@ -176,7 +183,7 @@ unsigned long kallsyms_lookup_name(const char *name)
176 unsigned int off; 183 unsigned int off;
177 184
178 for (i = 0, off = 0; i < kallsyms_num_syms; i++) { 185 for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
179 off = kallsyms_expand_symbol(off, namebuf); 186 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
180 187
181 if (strcmp(namebuf, name) == 0) 188 if (strcmp(namebuf, name) == 0)
182 return kallsyms_addresses[i]; 189 return kallsyms_addresses[i];
@@ -195,7 +202,7 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
195 int ret; 202 int ret;
196 203
197 for (i = 0, off = 0; i < kallsyms_num_syms; i++) { 204 for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
198 off = kallsyms_expand_symbol(off, namebuf); 205 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
199 ret = fn(data, namebuf, NULL, kallsyms_addresses[i]); 206 ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
200 if (ret != 0) 207 if (ret != 0)
201 return ret; 208 return ret;
@@ -294,7 +301,8 @@ const char *kallsyms_lookup(unsigned long addr,
294 301
295 pos = get_symbol_pos(addr, symbolsize, offset); 302 pos = get_symbol_pos(addr, symbolsize, offset);
296 /* Grab name */ 303 /* Grab name */
297 kallsyms_expand_symbol(get_symbol_offset(pos), namebuf); 304 kallsyms_expand_symbol(get_symbol_offset(pos),
305 namebuf, KSYM_NAME_LEN);
298 if (modname) 306 if (modname)
299 *modname = NULL; 307 *modname = NULL;
300 return namebuf; 308 return namebuf;
@@ -315,7 +323,8 @@ int lookup_symbol_name(unsigned long addr, char *symname)
315 323
316 pos = get_symbol_pos(addr, NULL, NULL); 324 pos = get_symbol_pos(addr, NULL, NULL);
317 /* Grab name */ 325 /* Grab name */
318 kallsyms_expand_symbol(get_symbol_offset(pos), symname); 326 kallsyms_expand_symbol(get_symbol_offset(pos),
327 symname, KSYM_NAME_LEN);
319 return 0; 328 return 0;
320 } 329 }
321 /* See if it's in a module. */ 330 /* See if it's in a module. */
@@ -333,7 +342,8 @@ int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
333 342
334 pos = get_symbol_pos(addr, size, offset); 343 pos = get_symbol_pos(addr, size, offset);
335 /* Grab name */ 344 /* Grab name */
336 kallsyms_expand_symbol(get_symbol_offset(pos), name); 345 kallsyms_expand_symbol(get_symbol_offset(pos),
346 name, KSYM_NAME_LEN);
337 modname[0] = '\0'; 347 modname[0] = '\0';
338 return 0; 348 return 0;
339 } 349 }
@@ -463,7 +473,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
463 473
464 iter->type = kallsyms_get_symbol_type(off); 474 iter->type = kallsyms_get_symbol_type(off);
465 475
466 off = kallsyms_expand_symbol(off, iter->name); 476 off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
467 477
468 return off - iter->nameoff; 478 return off - iter->nameoff;
469} 479}