aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2010-08-05 14:59:05 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-08-04 23:29:05 -0400
commit22e268ebecc549f1b1907f114cb44d6044bdee3c (patch)
treea1159e36de2a0ed6d3dcadd61622976971dd3b2d /kernel
parent9f85a4bbb1cf56f65b3d065a5f88204a757f2325 (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.c182
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
1701static 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 */
1702unsigned int __weak arch_mod_section_prepend(struct module *mod, 1735unsigned 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
2250static struct module *move_module(struct module *mod, 2291static 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
2355static 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
2386static 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. */
2316static noinline struct module *load_module(void __user *umod, 2411static 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);