diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2010-06-05 13:17:37 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-06-04 21:47:37 -0400 |
commit | be593f4ce4eb1bd40e38fdc403371f149f6f12eb (patch) | |
tree | 693aee53e2d87a8ae92b6276d2aef766e8154814 | |
parent | 3bafeb6247042dcbb72b0141ec7c7107de9f0b99 (diff) |
module: verify_export_symbols under the lock
It disabled preempt so it was "safe", but nothing stops another module
slipping in before this module is added to the global list now we don't
hold the lock the whole time.
So we check this just after we check for duplicate modules, and just
before we put the module in the global list.
(find_symbol finds symbols in coming and going modules, too).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-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); |