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