aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2008-01-14 03:55:03 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-01-14 11:52:22 -0500
commitcb2a52052cebe4716e83b9d2e53682ba00f67de6 (patch)
treedf35653a4ef0123c20df72f1c4355562553e9558
parent1a1b285c24e1468afe82b09330dde5192a6e0013 (diff)
modules: de-mutex more symbol lookup paths in the module code
Kyle McMartin reports sysrq_timer_list_show() can hit the module mutex from hard interrupt context. These paths don't need to though, since we long ago changed all the module list manipulation to occur via stop_machine(). Disabling preemption is enough. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: Ingo Molnar <mingo@elte.hu> Cc: Kyle McMartin <kyle@mcmartin.ca> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/module.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 91fe6958b6e1..c2e3e2e98801 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2214,29 +2214,34 @@ static const char *get_ksymbol(struct module *mod,
2214/* For kallsyms to ask for address resolution. NULL means not found. 2214/* For kallsyms to ask for address resolution. NULL means not found.
2215 We don't lock, as this is used for oops resolution and races are a 2215 We don't lock, as this is used for oops resolution and races are a
2216 lesser concern. */ 2216 lesser concern. */
2217/* FIXME: Risky: returns a pointer into a module w/o lock */
2217const char *module_address_lookup(unsigned long addr, 2218const char *module_address_lookup(unsigned long addr,
2218 unsigned long *size, 2219 unsigned long *size,
2219 unsigned long *offset, 2220 unsigned long *offset,
2220 char **modname) 2221 char **modname)
2221{ 2222{
2222 struct module *mod; 2223 struct module *mod;
2224 const char *ret = NULL;
2223 2225
2226 preempt_disable();
2224 list_for_each_entry(mod, &modules, list) { 2227 list_for_each_entry(mod, &modules, list) {
2225 if (within(addr, mod->module_init, mod->init_size) 2228 if (within(addr, mod->module_init, mod->init_size)
2226 || within(addr, mod->module_core, mod->core_size)) { 2229 || within(addr, mod->module_core, mod->core_size)) {
2227 if (modname) 2230 if (modname)
2228 *modname = mod->name; 2231 *modname = mod->name;
2229 return get_ksymbol(mod, addr, size, offset); 2232 ret = get_ksymbol(mod, addr, size, offset);
2233 break;
2230 } 2234 }
2231 } 2235 }
2232 return NULL; 2236 preempt_enable();
2237 return ret;
2233} 2238}
2234 2239
2235int lookup_module_symbol_name(unsigned long addr, char *symname) 2240int lookup_module_symbol_name(unsigned long addr, char *symname)
2236{ 2241{
2237 struct module *mod; 2242 struct module *mod;
2238 2243
2239 mutex_lock(&module_mutex); 2244 preempt_disable();
2240 list_for_each_entry(mod, &modules, list) { 2245 list_for_each_entry(mod, &modules, list) {
2241 if (within(addr, mod->module_init, mod->init_size) || 2246 if (within(addr, mod->module_init, mod->init_size) ||
2242 within(addr, mod->module_core, mod->core_size)) { 2247 within(addr, mod->module_core, mod->core_size)) {
@@ -2246,12 +2251,12 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
2246 if (!sym) 2251 if (!sym)
2247 goto out; 2252 goto out;
2248 strlcpy(symname, sym, KSYM_NAME_LEN); 2253 strlcpy(symname, sym, KSYM_NAME_LEN);
2249 mutex_unlock(&module_mutex); 2254 preempt_enable();
2250 return 0; 2255 return 0;
2251 } 2256 }
2252 } 2257 }
2253out: 2258out:
2254 mutex_unlock(&module_mutex); 2259 preempt_enable();
2255 return -ERANGE; 2260 return -ERANGE;
2256} 2261}
2257 2262
@@ -2260,7 +2265,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
2260{ 2265{
2261 struct module *mod; 2266 struct module *mod;
2262 2267
2263 mutex_lock(&module_mutex); 2268 preempt_disable();
2264 list_for_each_entry(mod, &modules, list) { 2269 list_for_each_entry(mod, &modules, list) {
2265 if (within(addr, mod->module_init, mod->init_size) || 2270 if (within(addr, mod->module_init, mod->init_size) ||
2266 within(addr, mod->module_core, mod->core_size)) { 2271 within(addr, mod->module_core, mod->core_size)) {
@@ -2273,12 +2278,12 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
2273 strlcpy(modname, mod->name, MODULE_NAME_LEN); 2278 strlcpy(modname, mod->name, MODULE_NAME_LEN);
2274 if (name) 2279 if (name)
2275 strlcpy(name, sym, KSYM_NAME_LEN); 2280 strlcpy(name, sym, KSYM_NAME_LEN);
2276 mutex_unlock(&module_mutex); 2281 preempt_enable();
2277 return 0; 2282 return 0;
2278 } 2283 }
2279 } 2284 }
2280out: 2285out:
2281 mutex_unlock(&module_mutex); 2286 preempt_enable();
2282 return -ERANGE; 2287 return -ERANGE;
2283} 2288}
2284 2289
@@ -2287,7 +2292,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
2287{ 2292{
2288 struct module *mod; 2293 struct module *mod;
2289 2294
2290 mutex_lock(&module_mutex); 2295 preempt_disable();
2291 list_for_each_entry(mod, &modules, list) { 2296 list_for_each_entry(mod, &modules, list) {
2292 if (symnum < mod->num_symtab) { 2297 if (symnum < mod->num_symtab) {
2293 *value = mod->symtab[symnum].st_value; 2298 *value = mod->symtab[symnum].st_value;
@@ -2296,12 +2301,12 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
2296 KSYM_NAME_LEN); 2301 KSYM_NAME_LEN);
2297 strlcpy(module_name, mod->name, MODULE_NAME_LEN); 2302 strlcpy(module_name, mod->name, MODULE_NAME_LEN);
2298 *exported = is_exported(name, mod); 2303 *exported = is_exported(name, mod);
2299 mutex_unlock(&module_mutex); 2304 preempt_enable();
2300 return 0; 2305 return 0;
2301 } 2306 }
2302 symnum -= mod->num_symtab; 2307 symnum -= mod->num_symtab;
2303 } 2308 }
2304 mutex_unlock(&module_mutex); 2309 preempt_enable();
2305 return -ERANGE; 2310 return -ERANGE;
2306} 2311}
2307 2312
@@ -2324,6 +2329,7 @@ unsigned long module_kallsyms_lookup_name(const char *name)
2324 unsigned long ret = 0; 2329 unsigned long ret = 0;
2325 2330
2326 /* Don't lock: we're in enough trouble already. */ 2331 /* Don't lock: we're in enough trouble already. */
2332 preempt_disable();
2327 if ((colon = strchr(name, ':')) != NULL) { 2333 if ((colon = strchr(name, ':')) != NULL) {
2328 *colon = '\0'; 2334 *colon = '\0';
2329 if ((mod = find_module(name)) != NULL) 2335 if ((mod = find_module(name)) != NULL)
@@ -2334,6 +2340,7 @@ unsigned long module_kallsyms_lookup_name(const char *name)
2334 if ((ret = mod_find_symname(mod, name)) != 0) 2340 if ((ret = mod_find_symname(mod, name)) != 0)
2335 break; 2341 break;
2336 } 2342 }
2343 preempt_enable();
2337 return ret; 2344 return ret;
2338} 2345}
2339#endif /* CONFIG_KALLSYMS */ 2346#endif /* CONFIG_KALLSYMS */