diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-29 17:13:22 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-29 01:13:23 -0500 |
commit | 6dd06c9fbe025f542bce4cdb91790c0f91962722 (patch) | |
tree | 5c946eb93f30c64fd435bdd6d1064880ef21557a | |
parent | bb9d3d56e792d2619cc0903df4ac01d86ac1261d (diff) |
module: make module_address_lookup safe
module_address_lookup releases preemption then returns a pointer into
the module space. The only user (kallsyms) copies the result, so just
do that under the preempt disable.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | include/linux/module.h | 22 | ||||
-rw-r--r-- | kernel/kallsyms.c | 11 | ||||
-rw-r--r-- | kernel/module.c | 22 |
3 files changed, 30 insertions, 25 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index c97bdb7eb957..aedc06be1de8 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -446,11 +446,14 @@ static inline void __module_get(struct module *module) | |||
446 | __mod ? __mod->name : "kernel"; \ | 446 | __mod ? __mod->name : "kernel"; \ |
447 | }) | 447 | }) |
448 | 448 | ||
449 | /* For kallsyms to ask for address resolution. NULL means not found. */ | 449 | /* For kallsyms to ask for address resolution. namebuf should be at |
450 | const char *module_address_lookup(unsigned long addr, | 450 | * least KSYM_NAME_LEN long: a pointer to namebuf is returned if |
451 | unsigned long *symbolsize, | 451 | * found, otherwise NULL. */ |
452 | unsigned long *offset, | 452 | char *module_address_lookup(unsigned long addr, |
453 | char **modname); | 453 | unsigned long *symbolsize, |
454 | unsigned long *offset, | ||
455 | char **modname, | ||
456 | char *namebuf); | ||
454 | int lookup_module_symbol_name(unsigned long addr, char *symname); | 457 | int lookup_module_symbol_name(unsigned long addr, char *symname); |
455 | int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); | 458 | int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); |
456 | 459 | ||
@@ -516,10 +519,11 @@ static inline void module_put(struct module *module) | |||
516 | #define module_name(mod) "kernel" | 519 | #define module_name(mod) "kernel" |
517 | 520 | ||
518 | /* For kallsyms to ask for address resolution. NULL means not found. */ | 521 | /* For kallsyms to ask for address resolution. NULL means not found. */ |
519 | static inline const char *module_address_lookup(unsigned long addr, | 522 | static inline char *module_address_lookup(unsigned long addr, |
520 | unsigned long *symbolsize, | 523 | unsigned long *symbolsize, |
521 | unsigned long *offset, | 524 | unsigned long *offset, |
522 | char **modname) | 525 | char **modname, |
526 | char *namebuf) | ||
523 | { | 527 | { |
524 | return NULL; | 528 | return NULL; |
525 | } | 529 | } |
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 2fc25810509e..7dadc71ce516 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
@@ -233,10 +233,11 @@ static unsigned long get_symbol_pos(unsigned long addr, | |||
233 | int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, | 233 | int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, |
234 | unsigned long *offset) | 234 | unsigned long *offset) |
235 | { | 235 | { |
236 | char namebuf[KSYM_NAME_LEN]; | ||
236 | if (is_ksym_addr(addr)) | 237 | if (is_ksym_addr(addr)) |
237 | return !!get_symbol_pos(addr, symbolsize, offset); | 238 | return !!get_symbol_pos(addr, symbolsize, offset); |
238 | 239 | ||
239 | return !!module_address_lookup(addr, symbolsize, offset, NULL); | 240 | return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf); |
240 | } | 241 | } |
241 | 242 | ||
242 | /* | 243 | /* |
@@ -251,8 +252,6 @@ const char *kallsyms_lookup(unsigned long addr, | |||
251 | unsigned long *offset, | 252 | unsigned long *offset, |
252 | char **modname, char *namebuf) | 253 | char **modname, char *namebuf) |
253 | { | 254 | { |
254 | const char *msym; | ||
255 | |||
256 | namebuf[KSYM_NAME_LEN - 1] = 0; | 255 | namebuf[KSYM_NAME_LEN - 1] = 0; |
257 | namebuf[0] = 0; | 256 | namebuf[0] = 0; |
258 | 257 | ||
@@ -268,10 +267,8 @@ const char *kallsyms_lookup(unsigned long addr, | |||
268 | } | 267 | } |
269 | 268 | ||
270 | /* see if it's in a module */ | 269 | /* see if it's in a module */ |
271 | msym = module_address_lookup(addr, symbolsize, offset, modname); | 270 | return module_address_lookup(addr, symbolsize, offset, modname, |
272 | if (msym) | 271 | namebuf); |
273 | return strncpy(namebuf, msym, KSYM_NAME_LEN - 1); | ||
274 | |||
275 | return NULL; | 272 | return NULL; |
276 | } | 273 | } |
277 | 274 | ||
diff --git a/kernel/module.c b/kernel/module.c index 12067ff34d01..e814cd7da634 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2230,14 +2230,13 @@ static const char *get_ksymbol(struct module *mod, | |||
2230 | return mod->strtab + mod->symtab[best].st_name; | 2230 | return mod->strtab + mod->symtab[best].st_name; |
2231 | } | 2231 | } |
2232 | 2232 | ||
2233 | /* For kallsyms to ask for address resolution. NULL means not found. | 2233 | /* For kallsyms to ask for address resolution. NULL means not found. Careful |
2234 | We don't lock, as this is used for oops resolution and races are a | 2234 | * not to lock to avoid deadlock on oopses, simply disable preemption. */ |
2235 | lesser concern. */ | 2235 | char *module_address_lookup(unsigned long addr, |
2236 | /* FIXME: Risky: returns a pointer into a module w/o lock */ | 2236 | unsigned long *size, |
2237 | const char *module_address_lookup(unsigned long addr, | 2237 | unsigned long *offset, |
2238 | unsigned long *size, | 2238 | char **modname, |
2239 | unsigned long *offset, | 2239 | char *namebuf) |
2240 | char **modname) | ||
2241 | { | 2240 | { |
2242 | struct module *mod; | 2241 | struct module *mod; |
2243 | const char *ret = NULL; | 2242 | const char *ret = NULL; |
@@ -2252,8 +2251,13 @@ const char *module_address_lookup(unsigned long addr, | |||
2252 | break; | 2251 | break; |
2253 | } | 2252 | } |
2254 | } | 2253 | } |
2254 | /* Make a copy in here where it's safe */ | ||
2255 | if (ret) { | ||
2256 | strncpy(namebuf, ret, KSYM_NAME_LEN - 1); | ||
2257 | ret = namebuf; | ||
2258 | } | ||
2255 | preempt_enable(); | 2259 | preempt_enable(); |
2256 | return ret; | 2260 | return (char *)ret; |
2257 | } | 2261 | } |
2258 | 2262 | ||
2259 | int lookup_module_symbol_name(unsigned long addr, char *symname) | 2263 | int lookup_module_symbol_name(unsigned long addr, char *symname) |