diff options
author | Chen Gang <gang.chen@asianux.com> | 2013-04-15 01:34:43 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-04-15 01:47:26 -0400 |
commit | e3f26752f0f8a6aade580115e1e68bcb1a4bc040 (patch) | |
tree | 04e818066d7d0faa64abfe55b4841da984f3812f /kernel/kallsyms.c | |
parent | 07c449bbc6aa514098c4f12c7b04180cec2417c6 (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>
Diffstat (limited to 'kernel/kallsyms.c')
-rw-r--r-- | kernel/kallsyms.c | 26 |
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 | */ |
89 | static unsigned int kallsyms_expand_symbol(unsigned int off, char *result) | 90 | static 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'; | 129 | tail: |
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 | } |