diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2010-08-05 14:59:05 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-08-04 23:29:05 -0400 |
commit | 22e268ebecc549f1b1907f114cb44d6044bdee3c (patch) | |
tree | a1159e36de2a0ed6d3dcadd61622976971dd3b2d /kernel | |
parent | 9f85a4bbb1cf56f65b3d065a5f88204a757f2325 (diff) |
module: refactor load_module part 5
1) Extract out the relocation loop into apply_relocations
2) Extract license and version checks into check_module_license_and_versions
3) Extract icache flushing into flush_module_icache
4) Move __obsparm warning into find_module_sections
5) Move license setting into check_modinfo.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 182 |
1 files changed, 106 insertions, 76 deletions
diff --git a/kernel/module.c b/kernel/module.c index 241bc41dd6be..b536db804ca0 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1698,6 +1698,39 @@ static int simplify_symbols(Elf_Shdr *sechdrs, | |||
1698 | return ret; | 1698 | return ret; |
1699 | } | 1699 | } |
1700 | 1700 | ||
1701 | static int apply_relocations(struct module *mod, | ||
1702 | Elf_Ehdr *hdr, | ||
1703 | Elf_Shdr *sechdrs, | ||
1704 | unsigned int symindex, | ||
1705 | unsigned int strindex) | ||
1706 | { | ||
1707 | unsigned int i; | ||
1708 | int err = 0; | ||
1709 | |||
1710 | /* Now do relocations. */ | ||
1711 | for (i = 1; i < hdr->e_shnum; i++) { | ||
1712 | const char *strtab = (char *)sechdrs[strindex].sh_addr; | ||
1713 | unsigned int info = sechdrs[i].sh_info; | ||
1714 | |||
1715 | /* Not a valid relocation section? */ | ||
1716 | if (info >= hdr->e_shnum) | ||
1717 | continue; | ||
1718 | |||
1719 | /* Don't bother with non-allocated sections */ | ||
1720 | if (!(sechdrs[info].sh_flags & SHF_ALLOC)) | ||
1721 | continue; | ||
1722 | |||
1723 | if (sechdrs[i].sh_type == SHT_REL) | ||
1724 | err = apply_relocate(sechdrs, strtab, symindex, i, mod); | ||
1725 | else if (sechdrs[i].sh_type == SHT_RELA) | ||
1726 | err = apply_relocate_add(sechdrs, strtab, symindex, i, | ||
1727 | mod); | ||
1728 | if (err < 0) | ||
1729 | break; | ||
1730 | } | ||
1731 | return err; | ||
1732 | } | ||
1733 | |||
1701 | /* Additional bytes needed by arch in front of individual sections */ | 1734 | /* Additional bytes needed by arch in front of individual sections */ |
1702 | unsigned int __weak arch_mod_section_prepend(struct module *mod, | 1735 | unsigned int __weak arch_mod_section_prepend(struct module *mod, |
1703 | unsigned int section) | 1736 | unsigned int section) |
@@ -2179,6 +2212,10 @@ static int check_modinfo(struct module *mod, | |||
2179 | " the quality is unknown, you have been warned.\n", | 2212 | " the quality is unknown, you have been warned.\n", |
2180 | mod->name); | 2213 | mod->name); |
2181 | } | 2214 | } |
2215 | |||
2216 | /* Set up license info based on the info section */ | ||
2217 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | ||
2218 | |||
2182 | return 0; | 2219 | return 0; |
2183 | } | 2220 | } |
2184 | 2221 | ||
@@ -2245,6 +2282,10 @@ static void find_module_sections(struct module *mod, Elf_Ehdr *hdr, | |||
2245 | sizeof(*mod->ftrace_callsites), | 2282 | sizeof(*mod->ftrace_callsites), |
2246 | &mod->num_ftrace_callsites); | 2283 | &mod->num_ftrace_callsites); |
2247 | #endif | 2284 | #endif |
2285 | |||
2286 | if (section_addr(hdr, sechdrs, secstrings, "__obsparm")) | ||
2287 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", | ||
2288 | mod->name); | ||
2248 | } | 2289 | } |
2249 | 2290 | ||
2250 | static struct module *move_module(struct module *mod, | 2291 | static struct module *move_module(struct module *mod, |
@@ -2311,6 +2352,60 @@ static struct module *move_module(struct module *mod, | |||
2311 | return mod; | 2352 | return mod; |
2312 | } | 2353 | } |
2313 | 2354 | ||
2355 | static int check_module_license_and_versions(struct module *mod, | ||
2356 | Elf_Shdr *sechdrs) | ||
2357 | { | ||
2358 | /* | ||
2359 | * ndiswrapper is under GPL by itself, but loads proprietary modules. | ||
2360 | * Don't use add_taint_module(), as it would prevent ndiswrapper from | ||
2361 | * using GPL-only symbols it needs. | ||
2362 | */ | ||
2363 | if (strcmp(mod->name, "ndiswrapper") == 0) | ||
2364 | add_taint(TAINT_PROPRIETARY_MODULE); | ||
2365 | |||
2366 | /* driverloader was caught wrongly pretending to be under GPL */ | ||
2367 | if (strcmp(mod->name, "driverloader") == 0) | ||
2368 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | ||
2369 | |||
2370 | #ifdef CONFIG_MODVERSIONS | ||
2371 | if ((mod->num_syms && !mod->crcs) | ||
2372 | || (mod->num_gpl_syms && !mod->gpl_crcs) | ||
2373 | || (mod->num_gpl_future_syms && !mod->gpl_future_crcs) | ||
2374 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
2375 | || (mod->num_unused_syms && !mod->unused_crcs) | ||
2376 | || (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs) | ||
2377 | #endif | ||
2378 | ) { | ||
2379 | return try_to_force_load(mod, | ||
2380 | "no versions for exported symbols"); | ||
2381 | } | ||
2382 | #endif | ||
2383 | return 0; | ||
2384 | } | ||
2385 | |||
2386 | static void flush_module_icache(const struct module *mod) | ||
2387 | { | ||
2388 | mm_segment_t old_fs; | ||
2389 | |||
2390 | /* flush the icache in correct context */ | ||
2391 | old_fs = get_fs(); | ||
2392 | set_fs(KERNEL_DS); | ||
2393 | |||
2394 | /* | ||
2395 | * Flush the instruction cache, since we've played with text. | ||
2396 | * Do it before processing of module parameters, so the module | ||
2397 | * can provide parameter accessor functions of its own. | ||
2398 | */ | ||
2399 | if (mod->module_init) | ||
2400 | flush_icache_range((unsigned long)mod->module_init, | ||
2401 | (unsigned long)mod->module_init | ||
2402 | + mod->init_size); | ||
2403 | flush_icache_range((unsigned long)mod->module_core, | ||
2404 | (unsigned long)mod->module_core + mod->core_size); | ||
2405 | |||
2406 | set_fs(old_fs); | ||
2407 | } | ||
2408 | |||
2314 | /* Allocate and load the module: note that size of section 0 is always | 2409 | /* Allocate and load the module: note that size of section 0 is always |
2315 | zero, and we rely on this for optional sections. */ | 2410 | zero, and we rely on this for optional sections. */ |
2316 | static noinline struct module *load_module(void __user *umod, | 2411 | static noinline struct module *load_module(void __user *umod, |
@@ -2331,8 +2426,6 @@ static noinline struct module *load_module(void __user *umod, | |||
2331 | struct _ddebug *debug = NULL; | 2426 | struct _ddebug *debug = NULL; |
2332 | unsigned int num_debug = 0; | 2427 | unsigned int num_debug = 0; |
2333 | 2428 | ||
2334 | mm_segment_t old_fs; | ||
2335 | |||
2336 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", | 2429 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
2337 | umod, len, uargs); | 2430 | umod, len, uargs); |
2338 | 2431 | ||
@@ -2453,20 +2546,13 @@ static noinline struct module *load_module(void __user *umod, | |||
2453 | if (err) | 2546 | if (err) |
2454 | goto free_init; | 2547 | goto free_init; |
2455 | 2548 | ||
2456 | /* Set up license info based on the info section */ | 2549 | /* Now we've got everything in the final locations, we can |
2457 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 2550 | * find optional sections. */ |
2458 | 2551 | find_module_sections(mod, hdr, sechdrs, secstrings); | |
2459 | /* | ||
2460 | * ndiswrapper is under GPL by itself, but loads proprietary modules. | ||
2461 | * Don't use add_taint_module(), as it would prevent ndiswrapper from | ||
2462 | * using GPL-only symbols it needs. | ||
2463 | */ | ||
2464 | if (strcmp(mod->name, "ndiswrapper") == 0) | ||
2465 | add_taint(TAINT_PROPRIETARY_MODULE); | ||
2466 | 2552 | ||
2467 | /* driverloader was caught wrongly pretending to be under GPL */ | 2553 | err = check_module_license_and_versions(mod, sechdrs); |
2468 | if (strcmp(mod->name, "driverloader") == 0) | 2554 | if (err) |
2469 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | 2555 | goto free_unload; |
2470 | 2556 | ||
2471 | /* Set up MODINFO_ATTR fields */ | 2557 | /* Set up MODINFO_ATTR fields */ |
2472 | setup_modinfo(mod, sechdrs, infoindex); | 2558 | setup_modinfo(mod, sechdrs, infoindex); |
@@ -2477,47 +2563,9 @@ static noinline struct module *load_module(void __user *umod, | |||
2477 | if (err < 0) | 2563 | if (err < 0) |
2478 | goto cleanup; | 2564 | goto cleanup; |
2479 | 2565 | ||
2480 | /* Now we've got everything in the final locations, we can | 2566 | err = apply_relocations(mod, hdr, sechdrs, symindex, strindex); |
2481 | * find optional sections. */ | 2567 | if (err < 0) |
2482 | find_module_sections(mod, hdr, sechdrs, secstrings); | 2568 | goto cleanup; |
2483 | |||
2484 | #ifdef CONFIG_MODVERSIONS | ||
2485 | if ((mod->num_syms && !mod->crcs) | ||
2486 | || (mod->num_gpl_syms && !mod->gpl_crcs) | ||
2487 | || (mod->num_gpl_future_syms && !mod->gpl_future_crcs) | ||
2488 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
2489 | || (mod->num_unused_syms && !mod->unused_crcs) | ||
2490 | || (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs) | ||
2491 | #endif | ||
2492 | ) { | ||
2493 | err = try_to_force_load(mod, | ||
2494 | "no versions for exported symbols"); | ||
2495 | if (err) | ||
2496 | goto cleanup; | ||
2497 | } | ||
2498 | #endif | ||
2499 | |||
2500 | /* Now do relocations. */ | ||
2501 | for (i = 1; i < hdr->e_shnum; i++) { | ||
2502 | const char *strtab = (char *)sechdrs[strindex].sh_addr; | ||
2503 | unsigned int info = sechdrs[i].sh_info; | ||
2504 | |||
2505 | /* Not a valid relocation section? */ | ||
2506 | if (info >= hdr->e_shnum) | ||
2507 | continue; | ||
2508 | |||
2509 | /* Don't bother with non-allocated sections */ | ||
2510 | if (!(sechdrs[info].sh_flags & SHF_ALLOC)) | ||
2511 | continue; | ||
2512 | |||
2513 | if (sechdrs[i].sh_type == SHT_REL) | ||
2514 | err = apply_relocate(sechdrs, strtab, symindex, i,mod); | ||
2515 | else if (sechdrs[i].sh_type == SHT_RELA) | ||
2516 | err = apply_relocate_add(sechdrs, strtab, symindex, i, | ||
2517 | mod); | ||
2518 | if (err < 0) | ||
2519 | goto cleanup; | ||
2520 | } | ||
2521 | 2569 | ||
2522 | /* Set up and sort exception table */ | 2570 | /* Set up and sort exception table */ |
2523 | mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table", | 2571 | mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table", |
@@ -2541,28 +2589,9 @@ static noinline struct module *load_module(void __user *umod, | |||
2541 | if (err < 0) | 2589 | if (err < 0) |
2542 | goto cleanup; | 2590 | goto cleanup; |
2543 | 2591 | ||
2544 | /* flush the icache in correct context */ | 2592 | flush_module_icache(mod); |
2545 | old_fs = get_fs(); | ||
2546 | set_fs(KERNEL_DS); | ||
2547 | |||
2548 | /* | ||
2549 | * Flush the instruction cache, since we've played with text. | ||
2550 | * Do it before processing of module parameters, so the module | ||
2551 | * can provide parameter accessor functions of its own. | ||
2552 | */ | ||
2553 | if (mod->module_init) | ||
2554 | flush_icache_range((unsigned long)mod->module_init, | ||
2555 | (unsigned long)mod->module_init | ||
2556 | + mod->init_size); | ||
2557 | flush_icache_range((unsigned long)mod->module_core, | ||
2558 | (unsigned long)mod->module_core + mod->core_size); | ||
2559 | |||
2560 | set_fs(old_fs); | ||
2561 | 2593 | ||
2562 | mod->args = args; | 2594 | mod->args = args; |
2563 | if (section_addr(hdr, sechdrs, secstrings, "__obsparm")) | ||
2564 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", | ||
2565 | mod->name); | ||
2566 | 2595 | ||
2567 | /* Now sew it into the lists so we can get lockdep and oops | 2596 | /* Now sew it into the lists so we can get lockdep and oops |
2568 | * info during argument parsing. Noone should access us, since | 2597 | * info during argument parsing. Noone should access us, since |
@@ -2619,6 +2648,7 @@ static noinline struct module *load_module(void __user *umod, | |||
2619 | module_arch_cleanup(mod); | 2648 | module_arch_cleanup(mod); |
2620 | cleanup: | 2649 | cleanup: |
2621 | free_modinfo(mod); | 2650 | free_modinfo(mod); |
2651 | free_unload: | ||
2622 | module_unload_free(mod); | 2652 | module_unload_free(mod); |
2623 | free_init: | 2653 | free_init: |
2624 | module_free(mod, mod->module_init); | 2654 | module_free(mod, mod->module_init); |