diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 26 |
1 files changed, 10 insertions, 16 deletions
diff --git a/kernel/module.c b/kernel/module.c index 28450047852a..f99558e1945a 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1571,6 +1571,8 @@ EXPORT_SYMBOL_GPL(__symbol_get); | |||
1571 | /* | 1571 | /* |
1572 | * Ensure that an exported symbol [global namespace] does not already exist | 1572 | * Ensure that an exported symbol [global namespace] does not already exist |
1573 | * in the kernel or in some other module's exported symbol table. | 1573 | * in the kernel or in some other module's exported symbol table. |
1574 | * | ||
1575 | * You must hold the module_mutex. | ||
1574 | */ | 1576 | */ |
1575 | static int verify_export_symbols(struct module *mod) | 1577 | static int verify_export_symbols(struct module *mod) |
1576 | { | 1578 | { |
@@ -1592,14 +1594,7 @@ static int verify_export_symbols(struct module *mod) | |||
1592 | 1594 | ||
1593 | for (i = 0; i < ARRAY_SIZE(arr); i++) { | 1595 | for (i = 0; i < ARRAY_SIZE(arr); i++) { |
1594 | for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { | 1596 | for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { |
1595 | const struct kernel_symbol *sym; | 1597 | if (find_symbol(s->name, &owner, NULL, true, false)) { |
1596 | |||
1597 | /* Stopping preemption makes find_symbol safe. */ | ||
1598 | preempt_disable(); | ||
1599 | sym = find_symbol(s->name, &owner, NULL, true, false); | ||
1600 | preempt_enable(); | ||
1601 | |||
1602 | if (sym) { | ||
1603 | printk(KERN_ERR | 1598 | printk(KERN_ERR |
1604 | "%s: exports duplicate symbol %s" | 1599 | "%s: exports duplicate symbol %s" |
1605 | " (owned by %s)\n", | 1600 | " (owned by %s)\n", |
@@ -2440,11 +2435,6 @@ static noinline struct module *load_module(void __user *umod, | |||
2440 | goto cleanup; | 2435 | goto cleanup; |
2441 | } | 2436 | } |
2442 | 2437 | ||
2443 | /* Find duplicate symbols */ | ||
2444 | err = verify_export_symbols(mod); | ||
2445 | if (err < 0) | ||
2446 | goto cleanup; | ||
2447 | |||
2448 | /* Set up and sort exception table */ | 2438 | /* Set up and sort exception table */ |
2449 | mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table", | 2439 | mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table", |
2450 | sizeof(*mod->extable), &mod->num_exentries); | 2440 | sizeof(*mod->extable), &mod->num_exentries); |
@@ -2506,10 +2496,14 @@ static noinline struct module *load_module(void __user *umod, | |||
2506 | mutex_lock(&module_mutex); | 2496 | mutex_lock(&module_mutex); |
2507 | if (find_module(mod->name)) { | 2497 | if (find_module(mod->name)) { |
2508 | err = -EEXIST; | 2498 | err = -EEXIST; |
2509 | /* This will also unlock the mutex */ | 2499 | goto unlock; |
2510 | goto already_exists; | ||
2511 | } | 2500 | } |
2512 | 2501 | ||
2502 | /* Find duplicate symbols */ | ||
2503 | err = verify_export_symbols(mod); | ||
2504 | if (err < 0) | ||
2505 | goto unlock; | ||
2506 | |||
2513 | list_add_rcu(&mod->list, &modules); | 2507 | list_add_rcu(&mod->list, &modules); |
2514 | mutex_unlock(&module_mutex); | 2508 | mutex_unlock(&module_mutex); |
2515 | 2509 | ||
@@ -2536,7 +2530,7 @@ static noinline struct module *load_module(void __user *umod, | |||
2536 | mutex_lock(&module_mutex); | 2530 | mutex_lock(&module_mutex); |
2537 | /* Unlink carefully: kallsyms could be walking list. */ | 2531 | /* Unlink carefully: kallsyms could be walking list. */ |
2538 | list_del_rcu(&mod->list); | 2532 | list_del_rcu(&mod->list); |
2539 | already_exists: | 2533 | unlock: |
2540 | mutex_unlock(&module_mutex); | 2534 | mutex_unlock(&module_mutex); |
2541 | synchronize_sched(); | 2535 | synchronize_sched(); |
2542 | module_arch_cleanup(mod); | 2536 | module_arch_cleanup(mod); |