diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/kernel/module.c b/kernel/module.c index 3202c9950073..c2e3e2e98801 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -81,7 +81,8 @@ int unregister_module_notifier(struct notifier_block * nb) | |||
81 | } | 81 | } |
82 | EXPORT_SYMBOL(unregister_module_notifier); | 82 | EXPORT_SYMBOL(unregister_module_notifier); |
83 | 83 | ||
84 | /* We require a truly strong try_module_get() */ | 84 | /* We require a truly strong try_module_get(): 0 means failure due to |
85 | ongoing or failed initialization etc. */ | ||
85 | static inline int strong_try_module_get(struct module *mod) | 86 | static inline int strong_try_module_get(struct module *mod) |
86 | { | 87 | { |
87 | if (mod && mod->state == MODULE_STATE_COMING) | 88 | if (mod && mod->state == MODULE_STATE_COMING) |
@@ -952,7 +953,8 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, | |||
952 | ret = __find_symbol(name, &owner, &crc, | 953 | ret = __find_symbol(name, &owner, &crc, |
953 | !(mod->taints & TAINT_PROPRIETARY_MODULE)); | 954 | !(mod->taints & TAINT_PROPRIETARY_MODULE)); |
954 | if (ret) { | 955 | if (ret) { |
955 | /* use_module can fail due to OOM, or module unloading */ | 956 | /* use_module can fail due to OOM, |
957 | or module initialization or unloading */ | ||
956 | if (!check_version(sechdrs, versindex, name, mod, crc) || | 958 | if (!check_version(sechdrs, versindex, name, mod, crc) || |
957 | !use_module(mod, owner)) | 959 | !use_module(mod, owner)) |
958 | ret = 0; | 960 | ret = 0; |
@@ -1369,7 +1371,7 @@ dup: | |||
1369 | return ret; | 1371 | return ret; |
1370 | } | 1372 | } |
1371 | 1373 | ||
1372 | /* Change all symbols so that sh_value encodes the pointer directly. */ | 1374 | /* Change all symbols so that st_value encodes the pointer directly. */ |
1373 | static int simplify_symbols(Elf_Shdr *sechdrs, | 1375 | static int simplify_symbols(Elf_Shdr *sechdrs, |
1374 | unsigned int symindex, | 1376 | unsigned int symindex, |
1375 | const char *strtab, | 1377 | const char *strtab, |
@@ -2212,29 +2214,34 @@ static const char *get_ksymbol(struct module *mod, | |||
2212 | /* For kallsyms to ask for address resolution. NULL means not found. | 2214 | /* For kallsyms to ask for address resolution. NULL means not found. |
2213 | 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 |
2214 | lesser concern. */ | 2216 | lesser concern. */ |
2217 | /* FIXME: Risky: returns a pointer into a module w/o lock */ | ||
2215 | const char *module_address_lookup(unsigned long addr, | 2218 | const char *module_address_lookup(unsigned long addr, |
2216 | unsigned long *size, | 2219 | unsigned long *size, |
2217 | unsigned long *offset, | 2220 | unsigned long *offset, |
2218 | char **modname) | 2221 | char **modname) |
2219 | { | 2222 | { |
2220 | struct module *mod; | 2223 | struct module *mod; |
2224 | const char *ret = NULL; | ||
2221 | 2225 | ||
2226 | preempt_disable(); | ||
2222 | list_for_each_entry(mod, &modules, list) { | 2227 | list_for_each_entry(mod, &modules, list) { |
2223 | if (within(addr, mod->module_init, mod->init_size) | 2228 | if (within(addr, mod->module_init, mod->init_size) |
2224 | || within(addr, mod->module_core, mod->core_size)) { | 2229 | || within(addr, mod->module_core, mod->core_size)) { |
2225 | if (modname) | 2230 | if (modname) |
2226 | *modname = mod->name; | 2231 | *modname = mod->name; |
2227 | return get_ksymbol(mod, addr, size, offset); | 2232 | ret = get_ksymbol(mod, addr, size, offset); |
2233 | break; | ||
2228 | } | 2234 | } |
2229 | } | 2235 | } |
2230 | return NULL; | 2236 | preempt_enable(); |
2237 | return ret; | ||
2231 | } | 2238 | } |
2232 | 2239 | ||
2233 | int lookup_module_symbol_name(unsigned long addr, char *symname) | 2240 | int lookup_module_symbol_name(unsigned long addr, char *symname) |
2234 | { | 2241 | { |
2235 | struct module *mod; | 2242 | struct module *mod; |
2236 | 2243 | ||
2237 | mutex_lock(&module_mutex); | 2244 | preempt_disable(); |
2238 | list_for_each_entry(mod, &modules, list) { | 2245 | list_for_each_entry(mod, &modules, list) { |
2239 | if (within(addr, mod->module_init, mod->init_size) || | 2246 | if (within(addr, mod->module_init, mod->init_size) || |
2240 | within(addr, mod->module_core, mod->core_size)) { | 2247 | within(addr, mod->module_core, mod->core_size)) { |
@@ -2244,12 +2251,12 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
2244 | if (!sym) | 2251 | if (!sym) |
2245 | goto out; | 2252 | goto out; |
2246 | strlcpy(symname, sym, KSYM_NAME_LEN); | 2253 | strlcpy(symname, sym, KSYM_NAME_LEN); |
2247 | mutex_unlock(&module_mutex); | 2254 | preempt_enable(); |
2248 | return 0; | 2255 | return 0; |
2249 | } | 2256 | } |
2250 | } | 2257 | } |
2251 | out: | 2258 | out: |
2252 | mutex_unlock(&module_mutex); | 2259 | preempt_enable(); |
2253 | return -ERANGE; | 2260 | return -ERANGE; |
2254 | } | 2261 | } |
2255 | 2262 | ||
@@ -2258,7 +2265,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
2258 | { | 2265 | { |
2259 | struct module *mod; | 2266 | struct module *mod; |
2260 | 2267 | ||
2261 | mutex_lock(&module_mutex); | 2268 | preempt_disable(); |
2262 | list_for_each_entry(mod, &modules, list) { | 2269 | list_for_each_entry(mod, &modules, list) { |
2263 | if (within(addr, mod->module_init, mod->init_size) || | 2270 | if (within(addr, mod->module_init, mod->init_size) || |
2264 | within(addr, mod->module_core, mod->core_size)) { | 2271 | within(addr, mod->module_core, mod->core_size)) { |
@@ -2271,12 +2278,12 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
2271 | strlcpy(modname, mod->name, MODULE_NAME_LEN); | 2278 | strlcpy(modname, mod->name, MODULE_NAME_LEN); |
2272 | if (name) | 2279 | if (name) |
2273 | strlcpy(name, sym, KSYM_NAME_LEN); | 2280 | strlcpy(name, sym, KSYM_NAME_LEN); |
2274 | mutex_unlock(&module_mutex); | 2281 | preempt_enable(); |
2275 | return 0; | 2282 | return 0; |
2276 | } | 2283 | } |
2277 | } | 2284 | } |
2278 | out: | 2285 | out: |
2279 | mutex_unlock(&module_mutex); | 2286 | preempt_enable(); |
2280 | return -ERANGE; | 2287 | return -ERANGE; |
2281 | } | 2288 | } |
2282 | 2289 | ||
@@ -2285,7 +2292,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
2285 | { | 2292 | { |
2286 | struct module *mod; | 2293 | struct module *mod; |
2287 | 2294 | ||
2288 | mutex_lock(&module_mutex); | 2295 | preempt_disable(); |
2289 | list_for_each_entry(mod, &modules, list) { | 2296 | list_for_each_entry(mod, &modules, list) { |
2290 | if (symnum < mod->num_symtab) { | 2297 | if (symnum < mod->num_symtab) { |
2291 | *value = mod->symtab[symnum].st_value; | 2298 | *value = mod->symtab[symnum].st_value; |
@@ -2294,12 +2301,12 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
2294 | KSYM_NAME_LEN); | 2301 | KSYM_NAME_LEN); |
2295 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); | 2302 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); |
2296 | *exported = is_exported(name, mod); | 2303 | *exported = is_exported(name, mod); |
2297 | mutex_unlock(&module_mutex); | 2304 | preempt_enable(); |
2298 | return 0; | 2305 | return 0; |
2299 | } | 2306 | } |
2300 | symnum -= mod->num_symtab; | 2307 | symnum -= mod->num_symtab; |
2301 | } | 2308 | } |
2302 | mutex_unlock(&module_mutex); | 2309 | preempt_enable(); |
2303 | return -ERANGE; | 2310 | return -ERANGE; |
2304 | } | 2311 | } |
2305 | 2312 | ||
@@ -2322,6 +2329,7 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
2322 | unsigned long ret = 0; | 2329 | unsigned long ret = 0; |
2323 | 2330 | ||
2324 | /* Don't lock: we're in enough trouble already. */ | 2331 | /* Don't lock: we're in enough trouble already. */ |
2332 | preempt_disable(); | ||
2325 | if ((colon = strchr(name, ':')) != NULL) { | 2333 | if ((colon = strchr(name, ':')) != NULL) { |
2326 | *colon = '\0'; | 2334 | *colon = '\0'; |
2327 | if ((mod = find_module(name)) != NULL) | 2335 | if ((mod = find_module(name)) != NULL) |
@@ -2332,6 +2340,7 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
2332 | if ((ret = mod_find_symname(mod, name)) != 0) | 2340 | if ((ret = mod_find_symname(mod, name)) != 0) |
2333 | break; | 2341 | break; |
2334 | } | 2342 | } |
2343 | preempt_enable(); | ||
2335 | return ret; | 2344 | return ret; |
2336 | } | 2345 | } |
2337 | #endif /* CONFIG_KALLSYMS */ | 2346 | #endif /* CONFIG_KALLSYMS */ |