Commit 22e268ebecc549f1b1907f114cb44d6044bdee3c
1 parent
9f85a4bbb1
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 106 additions and 76 deletions Side-by-side Diff
kernel/module.c
... | ... | @@ -1698,6 +1698,39 @@ |
1698 | 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 | 1734 | /* Additional bytes needed by arch in front of individual sections */ |
1702 | 1735 | unsigned int __weak arch_mod_section_prepend(struct module *mod, |
1703 | 1736 | unsigned int section) |
... | ... | @@ -2179,6 +2212,10 @@ |
2179 | 2212 | " the quality is unknown, you have been warned.\n", |
2180 | 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 | 2219 | return 0; |
2183 | 2220 | } |
2184 | 2221 | |
... | ... | @@ -2245,6 +2282,10 @@ |
2245 | 2282 | sizeof(*mod->ftrace_callsites), |
2246 | 2283 | &mod->num_ftrace_callsites); |
2247 | 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 | 2291 | static struct module *move_module(struct module *mod, |
... | ... | @@ -2311,6 +2352,60 @@ |
2311 | 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 | 2409 | /* Allocate and load the module: note that size of section 0 is always |
2315 | 2410 | zero, and we rely on this for optional sections. */ |
2316 | 2411 | static noinline struct module *load_module(void __user *umod, |
... | ... | @@ -2331,8 +2426,6 @@ |
2331 | 2426 | struct _ddebug *debug = NULL; |
2332 | 2427 | unsigned int num_debug = 0; |
2333 | 2428 | |
2334 | - mm_segment_t old_fs; | |
2335 | - | |
2336 | 2429 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
2337 | 2430 | umod, len, uargs); |
2338 | 2431 | |
2339 | 2432 | |
2340 | 2433 | |
... | ... | @@ -2453,21 +2546,14 @@ |
2453 | 2546 | if (err) |
2454 | 2547 | goto free_init; |
2455 | 2548 | |
2456 | - /* Set up license info based on the info section */ | |
2457 | - set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | |
2549 | + /* Now we've got everything in the final locations, we can | |
2550 | + * find optional sections. */ | |
2551 | + find_module_sections(mod, hdr, sechdrs, secstrings); | |
2458 | 2552 | |
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); | |
2553 | + err = check_module_license_and_versions(mod, sechdrs); | |
2554 | + if (err) | |
2555 | + goto free_unload; | |
2466 | 2556 | |
2467 | - /* driverloader was caught wrongly pretending to be under GPL */ | |
2468 | - if (strcmp(mod->name, "driverloader") == 0) | |
2469 | - add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | |
2470 | - | |
2471 | 2557 | /* Set up MODINFO_ATTR fields */ |
2472 | 2558 | setup_modinfo(mod, sechdrs, infoindex); |
2473 | 2559 | |
2474 | 2560 | |
... | ... | @@ -2477,48 +2563,10 @@ |
2477 | 2563 | if (err < 0) |
2478 | 2564 | goto cleanup; |
2479 | 2565 | |
2480 | - /* Now we've got everything in the final locations, we can | |
2481 | - * find optional sections. */ | |
2482 | - find_module_sections(mod, hdr, sechdrs, secstrings); | |
2566 | + err = apply_relocations(mod, hdr, sechdrs, symindex, strindex); | |
2567 | + if (err < 0) | |
2568 | + goto cleanup; | |
2483 | 2569 | |
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 | - | |
2522 | 2570 | /* Set up and sort exception table */ |
2523 | 2571 | mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table", |
2524 | 2572 | sizeof(*mod->extable), &mod->num_exentries); |
2525 | 2573 | |
2526 | 2574 | |
... | ... | @@ -2541,28 +2589,9 @@ |
2541 | 2589 | if (err < 0) |
2542 | 2590 | goto cleanup; |
2543 | 2591 | |
2544 | - /* flush the icache in correct context */ | |
2545 | - old_fs = get_fs(); | |
2546 | - set_fs(KERNEL_DS); | |
2592 | + flush_module_icache(mod); | |
2547 | 2593 | |
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 | - | |
2562 | 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 | 2596 | /* Now sew it into the lists so we can get lockdep and oops |
2568 | 2597 | * info during argument parsing. Noone should access us, since |
... | ... | @@ -2619,6 +2648,7 @@ |
2619 | 2648 | module_arch_cleanup(mod); |
2620 | 2649 | cleanup: |
2621 | 2650 | free_modinfo(mod); |
2651 | + free_unload: | |
2622 | 2652 | module_unload_free(mod); |
2623 | 2653 | free_init: |
2624 | 2654 | module_free(mod, mod->module_init); |