diff options
Diffstat (limited to 'kernel/module.c')
| -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); |
