diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 47 |
1 files changed, 22 insertions, 25 deletions
diff --git a/kernel/module.c b/kernel/module.c index 3d256681ab64..c0f1826e2d9e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/string.h> | 42 | #include <linux/string.h> |
43 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
44 | #include <linux/unwind.h> | 44 | #include <linux/unwind.h> |
45 | #include <linux/rculist.h> | ||
45 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
46 | #include <asm/cacheflush.h> | 47 | #include <asm/cacheflush.h> |
47 | #include <linux/license.h> | 48 | #include <linux/license.h> |
@@ -63,7 +64,7 @@ | |||
63 | #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) | 64 | #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) |
64 | 65 | ||
65 | /* List of modules, protected by module_mutex or preempt_disable | 66 | /* List of modules, protected by module_mutex or preempt_disable |
66 | * (add/delete uses stop_machine). */ | 67 | * (delete uses stop_machine/add uses RCU list operations). */ |
67 | static DEFINE_MUTEX(module_mutex); | 68 | static DEFINE_MUTEX(module_mutex); |
68 | static LIST_HEAD(modules); | 69 | static LIST_HEAD(modules); |
69 | 70 | ||
@@ -241,7 +242,7 @@ static bool each_symbol(bool (*fn)(const struct symsearch *arr, | |||
241 | if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data)) | 242 | if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data)) |
242 | return true; | 243 | return true; |
243 | 244 | ||
244 | list_for_each_entry(mod, &modules, list) { | 245 | list_for_each_entry_rcu(mod, &modules, list) { |
245 | struct symsearch arr[] = { | 246 | struct symsearch arr[] = { |
246 | { mod->syms, mod->syms + mod->num_syms, mod->crcs, | 247 | { mod->syms, mod->syms + mod->num_syms, mod->crcs, |
247 | NOT_GPL_ONLY, false }, | 248 | NOT_GPL_ONLY, false }, |
@@ -1417,17 +1418,6 @@ static void mod_kobject_remove(struct module *mod) | |||
1417 | } | 1418 | } |
1418 | 1419 | ||
1419 | /* | 1420 | /* |
1420 | * link the module with the whole machine is stopped with interrupts off | ||
1421 | * - this defends against kallsyms not taking locks | ||
1422 | */ | ||
1423 | static int __link_module(void *_mod) | ||
1424 | { | ||
1425 | struct module *mod = _mod; | ||
1426 | list_add(&mod->list, &modules); | ||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | /* | ||
1431 | * unlink the module with the whole machine is stopped with interrupts off | 1421 | * unlink the module with the whole machine is stopped with interrupts off |
1432 | * - this defends against kallsyms not taking locks | 1422 | * - this defends against kallsyms not taking locks |
1433 | */ | 1423 | */ |
@@ -2239,9 +2229,13 @@ static noinline struct module *load_module(void __user *umod, | |||
2239 | mod->name); | 2229 | mod->name); |
2240 | 2230 | ||
2241 | /* Now sew it into the lists so we can get lockdep and oops | 2231 | /* Now sew it into the lists so we can get lockdep and oops |
2242 | * info during argument parsing. Noone should access us, since | 2232 | * info during argument parsing. Noone should access us, since |
2243 | * strong_try_module_get() will fail. */ | 2233 | * strong_try_module_get() will fail. |
2244 | stop_machine(__link_module, mod, NULL); | 2234 | * lockdep/oops can run asynchronous, so use the RCU list insertion |
2235 | * function to insert in a way safe to concurrent readers. | ||
2236 | * The mutex protects against concurrent writers. | ||
2237 | */ | ||
2238 | list_add_rcu(&mod->list, &modules); | ||
2245 | 2239 | ||
2246 | err = parse_args(mod->name, mod->args, kp, num_kp, NULL); | 2240 | err = parse_args(mod->name, mod->args, kp, num_kp, NULL); |
2247 | if (err < 0) | 2241 | if (err < 0) |
@@ -2436,7 +2430,7 @@ const char *module_address_lookup(unsigned long addr, | |||
2436 | const char *ret = NULL; | 2430 | const char *ret = NULL; |
2437 | 2431 | ||
2438 | preempt_disable(); | 2432 | preempt_disable(); |
2439 | list_for_each_entry(mod, &modules, list) { | 2433 | list_for_each_entry_rcu(mod, &modules, list) { |
2440 | if (within(addr, mod->module_init, mod->init_size) | 2434 | if (within(addr, mod->module_init, mod->init_size) |
2441 | || within(addr, mod->module_core, mod->core_size)) { | 2435 | || within(addr, mod->module_core, mod->core_size)) { |
2442 | if (modname) | 2436 | if (modname) |
@@ -2459,7 +2453,7 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
2459 | struct module *mod; | 2453 | struct module *mod; |
2460 | 2454 | ||
2461 | preempt_disable(); | 2455 | preempt_disable(); |
2462 | list_for_each_entry(mod, &modules, list) { | 2456 | list_for_each_entry_rcu(mod, &modules, list) { |
2463 | if (within(addr, mod->module_init, mod->init_size) || | 2457 | if (within(addr, mod->module_init, mod->init_size) || |
2464 | within(addr, mod->module_core, mod->core_size)) { | 2458 | within(addr, mod->module_core, mod->core_size)) { |
2465 | const char *sym; | 2459 | const char *sym; |
@@ -2483,7 +2477,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
2483 | struct module *mod; | 2477 | struct module *mod; |
2484 | 2478 | ||
2485 | preempt_disable(); | 2479 | preempt_disable(); |
2486 | list_for_each_entry(mod, &modules, list) { | 2480 | list_for_each_entry_rcu(mod, &modules, list) { |
2487 | if (within(addr, mod->module_init, mod->init_size) || | 2481 | if (within(addr, mod->module_init, mod->init_size) || |
2488 | within(addr, mod->module_core, mod->core_size)) { | 2482 | within(addr, mod->module_core, mod->core_size)) { |
2489 | const char *sym; | 2483 | const char *sym; |
@@ -2510,7 +2504,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
2510 | struct module *mod; | 2504 | struct module *mod; |
2511 | 2505 | ||
2512 | preempt_disable(); | 2506 | preempt_disable(); |
2513 | list_for_each_entry(mod, &modules, list) { | 2507 | list_for_each_entry_rcu(mod, &modules, list) { |
2514 | if (symnum < mod->num_symtab) { | 2508 | if (symnum < mod->num_symtab) { |
2515 | *value = mod->symtab[symnum].st_value; | 2509 | *value = mod->symtab[symnum].st_value; |
2516 | *type = mod->symtab[symnum].st_info; | 2510 | *type = mod->symtab[symnum].st_info; |
@@ -2553,7 +2547,7 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
2553 | ret = mod_find_symname(mod, colon+1); | 2547 | ret = mod_find_symname(mod, colon+1); |
2554 | *colon = ':'; | 2548 | *colon = ':'; |
2555 | } else { | 2549 | } else { |
2556 | list_for_each_entry(mod, &modules, list) | 2550 | list_for_each_entry_rcu(mod, &modules, list) |
2557 | if ((ret = mod_find_symname(mod, name)) != 0) | 2551 | if ((ret = mod_find_symname(mod, name)) != 0) |
2558 | break; | 2552 | break; |
2559 | } | 2553 | } |
@@ -2656,7 +2650,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) | |||
2656 | struct module *mod; | 2650 | struct module *mod; |
2657 | 2651 | ||
2658 | preempt_disable(); | 2652 | preempt_disable(); |
2659 | list_for_each_entry(mod, &modules, list) { | 2653 | list_for_each_entry_rcu(mod, &modules, list) { |
2660 | if (mod->num_exentries == 0) | 2654 | if (mod->num_exentries == 0) |
2661 | continue; | 2655 | continue; |
2662 | 2656 | ||
@@ -2682,7 +2676,7 @@ int is_module_address(unsigned long addr) | |||
2682 | 2676 | ||
2683 | preempt_disable(); | 2677 | preempt_disable(); |
2684 | 2678 | ||
2685 | list_for_each_entry(mod, &modules, list) { | 2679 | list_for_each_entry_rcu(mod, &modules, list) { |
2686 | if (within(addr, mod->module_core, mod->core_size)) { | 2680 | if (within(addr, mod->module_core, mod->core_size)) { |
2687 | preempt_enable(); | 2681 | preempt_enable(); |
2688 | return 1; | 2682 | return 1; |
@@ -2703,7 +2697,7 @@ struct module *__module_text_address(unsigned long addr) | |||
2703 | if (addr < module_addr_min || addr > module_addr_max) | 2697 | if (addr < module_addr_min || addr > module_addr_max) |
2704 | return NULL; | 2698 | return NULL; |
2705 | 2699 | ||
2706 | list_for_each_entry(mod, &modules, list) | 2700 | list_for_each_entry_rcu(mod, &modules, list) |
2707 | if (within(addr, mod->module_init, mod->init_text_size) | 2701 | if (within(addr, mod->module_init, mod->init_text_size) |
2708 | || within(addr, mod->module_core, mod->core_text_size)) | 2702 | || within(addr, mod->module_core, mod->core_text_size)) |
2709 | return mod; | 2703 | return mod; |
@@ -2728,8 +2722,11 @@ void print_modules(void) | |||
2728 | char buf[8]; | 2722 | char buf[8]; |
2729 | 2723 | ||
2730 | printk("Modules linked in:"); | 2724 | printk("Modules linked in:"); |
2731 | list_for_each_entry(mod, &modules, list) | 2725 | /* Most callers should already have preempt disabled, but make sure */ |
2726 | preempt_disable(); | ||
2727 | list_for_each_entry_rcu(mod, &modules, list) | ||
2732 | printk(" %s%s", mod->name, module_flags(mod, buf)); | 2728 | printk(" %s%s", mod->name, module_flags(mod, buf)); |
2729 | preempt_enable(); | ||
2733 | if (last_unloaded_module[0]) | 2730 | if (last_unloaded_module[0]) |
2734 | printk(" [last unloaded: %s]", last_unloaded_module); | 2731 | printk(" [last unloaded: %s]", last_unloaded_module); |
2735 | printk("\n"); | 2732 | printk("\n"); |