aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c228
1 files changed, 125 insertions, 103 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 79545bda358a..cb40a4e64a0e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2148,8 +2148,17 @@ static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
2148} 2148}
2149#endif 2149#endif
2150 2150
2151static int copy_and_check(Elf_Ehdr **hdrp, 2151struct load_info {
2152 const void __user *umod, unsigned long len) 2152 Elf_Ehdr *hdr;
2153 unsigned long len;
2154 Elf_Shdr *sechdrs;
2155 char *secstrings, *args, *strtab;
2156 struct {
2157 unsigned int sym, str, mod, vers, info, pcpu;
2158 } index;
2159};
2160
2161static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len)
2153{ 2162{
2154 int err; 2163 int err;
2155 Elf_Ehdr *hdr; 2164 Elf_Ehdr *hdr;
@@ -2159,7 +2168,7 @@ static int copy_and_check(Elf_Ehdr **hdrp,
2159 2168
2160 /* Suck in entire file: we'll want most of it. */ 2169 /* Suck in entire file: we'll want most of it. */
2161 /* vmalloc barfs on "unusual" numbers. Check here */ 2170 /* vmalloc barfs on "unusual" numbers. Check here */
2162 if (len > 64 * 1024 * 1024 || (hdr = *hdrp = vmalloc(len)) == NULL) 2171 if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
2163 return -ENOMEM; 2172 return -ENOMEM;
2164 2173
2165 if (copy_from_user(hdr, umod, len) != 0) { 2174 if (copy_from_user(hdr, umod, len) != 0) {
@@ -2181,6 +2190,8 @@ static int copy_and_check(Elf_Ehdr **hdrp,
2181 err = -ENOEXEC; 2190 err = -ENOEXEC;
2182 goto free_hdr; 2191 goto free_hdr;
2183 } 2192 }
2193 info->hdr = hdr;
2194 info->len = len;
2184 return 0; 2195 return 0;
2185 2196
2186free_hdr: 2197free_hdr:
@@ -2188,6 +2199,80 @@ free_hdr:
2188 return err; 2199 return err;
2189} 2200}
2190 2201
2202/*
2203 * Set up our basic convenience variables (pointers to section headers,
2204 * search for module section index etc), and do some basic section
2205 * verification.
2206 *
2207 * Return the temporary module pointer (we'll replace it with the final
2208 * one when we move the module sections around).
2209 */
2210static struct module *setup_load_info(struct load_info *info)
2211{
2212 unsigned int i;
2213 struct module *mod;
2214
2215 /* Set up the convenience variables */
2216 info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
2217 info->secstrings = (void *)info->hdr + info->sechdrs[info->hdr->e_shstrndx].sh_offset;
2218 info->sechdrs[0].sh_addr = 0;
2219
2220 for (i = 1; i < info->hdr->e_shnum; i++) {
2221 if (info->sechdrs[i].sh_type != SHT_NOBITS
2222 && info->len < info->sechdrs[i].sh_offset + info->sechdrs[i].sh_size)
2223 goto truncated;
2224
2225 /* Mark all sections sh_addr with their address in the
2226 temporary image. */
2227 info->sechdrs[i].sh_addr = (size_t)info->hdr + info->sechdrs[i].sh_offset;
2228
2229 /* Internal symbols and strings. */
2230 if (info->sechdrs[i].sh_type == SHT_SYMTAB) {
2231 info->index.sym = i;
2232 info->index.str = info->sechdrs[i].sh_link;
2233 info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset;
2234 }
2235#ifndef CONFIG_MODULE_UNLOAD
2236 /* Don't load .exit sections */
2237 if (strstarts(info->secstrings+info->sechdrs[i].sh_name, ".exit"))
2238 info->sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
2239#endif
2240 }
2241
2242 info->index.mod = find_sec(info->hdr, info->sechdrs, info->secstrings,
2243 ".gnu.linkonce.this_module");
2244 if (!info->index.mod) {
2245 printk(KERN_WARNING "No module found in object\n");
2246 return ERR_PTR(-ENOEXEC);
2247 }
2248 /* This is temporary: point mod into copy of data. */
2249 mod = (void *)info->sechdrs[info->index.mod].sh_addr;
2250
2251 if (info->index.sym == 0) {
2252 printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",
2253 mod->name);
2254 return ERR_PTR(-ENOEXEC);
2255 }
2256
2257 info->index.vers = find_sec(info->hdr, info->sechdrs, info->secstrings, "__versions");
2258 info->index.info = find_sec(info->hdr, info->sechdrs, info->secstrings, ".modinfo");
2259 info->index.pcpu = find_pcpusec(info->hdr, info->sechdrs, info->secstrings);
2260
2261 /* Don't keep modinfo and version sections. */
2262 info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
2263 info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
2264
2265 /* Check module struct version now, before we try to use module. */
2266 if (!check_modstruct_version(info->sechdrs, info->index.vers, mod))
2267 return ERR_PTR(-ENOEXEC);
2268
2269 return mod;
2270
2271 truncated:
2272 printk(KERN_ERR "Module len %lu truncated\n", info->len);
2273 return ERR_PTR(-ENOEXEC);
2274}
2275
2191static int check_modinfo(struct module *mod, 2276static int check_modinfo(struct module *mod,
2192 const Elf_Shdr *sechdrs, 2277 const Elf_Shdr *sechdrs,
2193 unsigned int infoindex, unsigned int versindex) 2278 unsigned int infoindex, unsigned int versindex)
@@ -2412,13 +2497,7 @@ static noinline struct module *load_module(void __user *umod,
2412 unsigned long len, 2497 unsigned long len,
2413 const char __user *uargs) 2498 const char __user *uargs)
2414{ 2499{
2415 Elf_Ehdr *hdr; 2500 struct load_info info = { NULL, };
2416 Elf_Shdr *sechdrs;
2417 char *secstrings, *args, *strtab = NULL;
2418 unsigned int i;
2419 unsigned int symindex = 0;
2420 unsigned int strindex = 0;
2421 unsigned int modindex, versindex, infoindex, pcpuindex;
2422 struct module *mod; 2501 struct module *mod;
2423 long err; 2502 long err;
2424 unsigned long symoffs, stroffs, *strmap; 2503 unsigned long symoffs, stroffs, *strmap;
@@ -2429,80 +2508,28 @@ static noinline struct module *load_module(void __user *umod,
2429 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 2508 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
2430 umod, len, uargs); 2509 umod, len, uargs);
2431 2510
2432 err = copy_and_check(&hdr, umod, len); 2511 err = copy_and_check(&info, umod, len);
2433 if (err) 2512 if (err)
2434 return ERR_PTR(err); 2513 return ERR_PTR(err);
2435 2514
2436 /* Convenience variables */ 2515 mod = setup_load_info(&info);
2437 sechdrs = (void *)hdr + hdr->e_shoff; 2516 if (IS_ERR(mod)) {
2438 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 2517 err = PTR_ERR(mod);
2439 sechdrs[0].sh_addr = 0;
2440
2441 for (i = 1; i < hdr->e_shnum; i++) {
2442 if (sechdrs[i].sh_type != SHT_NOBITS
2443 && len < sechdrs[i].sh_offset + sechdrs[i].sh_size)
2444 goto truncated;
2445
2446 /* Mark all sections sh_addr with their address in the
2447 temporary image. */
2448 sechdrs[i].sh_addr = (size_t)hdr + sechdrs[i].sh_offset;
2449
2450 /* Internal symbols and strings. */
2451 if (sechdrs[i].sh_type == SHT_SYMTAB) {
2452 symindex = i;
2453 strindex = sechdrs[i].sh_link;
2454 strtab = (char *)hdr + sechdrs[strindex].sh_offset;
2455 }
2456#ifndef CONFIG_MODULE_UNLOAD
2457 /* Don't load .exit sections */
2458 if (strstarts(secstrings+sechdrs[i].sh_name, ".exit"))
2459 sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
2460#endif
2461 }
2462
2463 modindex = find_sec(hdr, sechdrs, secstrings,
2464 ".gnu.linkonce.this_module");
2465 if (!modindex) {
2466 printk(KERN_WARNING "No module found in object\n");
2467 err = -ENOEXEC;
2468 goto free_hdr;
2469 }
2470 /* This is temporary: point mod into copy of data. */
2471 mod = (void *)sechdrs[modindex].sh_addr;
2472
2473 if (symindex == 0) {
2474 printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",
2475 mod->name);
2476 err = -ENOEXEC;
2477 goto free_hdr;
2478 }
2479
2480 versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
2481 infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
2482 pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
2483
2484 /* Don't keep modinfo and version sections. */
2485 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2486 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2487
2488 /* Check module struct version now, before we try to use module. */
2489 if (!check_modstruct_version(sechdrs, versindex, mod)) {
2490 err = -ENOEXEC;
2491 goto free_hdr; 2518 goto free_hdr;
2492 } 2519 }
2493 2520
2494 err = check_modinfo(mod, sechdrs, infoindex, versindex); 2521 err = check_modinfo(mod, info.sechdrs, info.index.info, info.index.vers);
2495 if (err) 2522 if (err)
2496 goto free_hdr; 2523 goto free_hdr;
2497 2524
2498 /* Now copy in args */ 2525 /* Now copy in args */
2499 args = strndup_user(uargs, ~0UL >> 1); 2526 info.args = strndup_user(uargs, ~0UL >> 1);
2500 if (IS_ERR(args)) { 2527 if (IS_ERR(info.args)) {
2501 err = PTR_ERR(args); 2528 err = PTR_ERR(info.args);
2502 goto free_hdr; 2529 goto free_hdr;
2503 } 2530 }
2504 2531
2505 strmap = kzalloc(BITS_TO_LONGS(sechdrs[strindex].sh_size) 2532 strmap = kzalloc(BITS_TO_LONGS(info.sechdrs[info.index.str].sh_size)
2506 * sizeof(long), GFP_KERNEL); 2533 * sizeof(long), GFP_KERNEL);
2507 if (!strmap) { 2534 if (!strmap) {
2508 err = -ENOMEM; 2535 err = -ENOMEM;
@@ -2512,17 +2539,17 @@ static noinline struct module *load_module(void __user *umod,
2512 mod->state = MODULE_STATE_COMING; 2539 mod->state = MODULE_STATE_COMING;
2513 2540
2514 /* Allow arches to frob section contents and sizes. */ 2541 /* Allow arches to frob section contents and sizes. */
2515 err = module_frob_arch_sections(hdr, sechdrs, secstrings, mod); 2542 err = module_frob_arch_sections(info.hdr, info.sechdrs, info.secstrings, mod);
2516 if (err < 0) 2543 if (err < 0)
2517 goto free_mod; 2544 goto free_mod;
2518 2545
2519 if (pcpuindex) { 2546 if (info.index.pcpu) {
2520 /* We have a special allocation for this section. */ 2547 /* We have a special allocation for this section. */
2521 err = percpu_modalloc(mod, sechdrs[pcpuindex].sh_size, 2548 err = percpu_modalloc(mod, info.sechdrs[info.index.pcpu].sh_size,
2522 sechdrs[pcpuindex].sh_addralign); 2549 info.sechdrs[info.index.pcpu].sh_addralign);
2523 if (err) 2550 if (err)
2524 goto free_mod; 2551 goto free_mod;
2525 sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2552 info.sechdrs[info.index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
2526 } 2553 }
2527 /* Keep this around for failure path. */ 2554 /* Keep this around for failure path. */
2528 percpu = mod_percpu(mod); 2555 percpu = mod_percpu(mod);
@@ -2530,12 +2557,12 @@ static noinline struct module *load_module(void __user *umod,
2530 /* Determine total sizes, and put offsets in sh_entsize. For now 2557 /* Determine total sizes, and put offsets in sh_entsize. For now
2531 this is done generically; there doesn't appear to be any 2558 this is done generically; there doesn't appear to be any
2532 special cases for the architectures. */ 2559 special cases for the architectures. */
2533 layout_sections(mod, hdr, sechdrs, secstrings); 2560 layout_sections(mod, info.hdr, info.sechdrs, info.secstrings);
2534 symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr, 2561 symoffs = layout_symtab(mod, info.sechdrs, info.index.sym, info.index.str, info.hdr,
2535 secstrings, &stroffs, strmap); 2562 info.secstrings, &stroffs, strmap);
2536 2563
2537 /* Allocate and move to the final place */ 2564 /* Allocate and move to the final place */
2538 mod = move_module(mod, hdr, sechdrs, secstrings, modindex); 2565 mod = move_module(mod, info.hdr, info.sechdrs, info.secstrings, info.index.mod);
2539 if (IS_ERR(mod)) { 2566 if (IS_ERR(mod)) {
2540 err = PTR_ERR(mod); 2567 err = PTR_ERR(mod);
2541 goto free_percpu; 2568 goto free_percpu;
@@ -2548,50 +2575,50 @@ static noinline struct module *load_module(void __user *umod,
2548 2575
2549 /* Now we've got everything in the final locations, we can 2576 /* Now we've got everything in the final locations, we can
2550 * find optional sections. */ 2577 * find optional sections. */
2551 find_module_sections(mod, hdr, sechdrs, secstrings); 2578 find_module_sections(mod, info.hdr, info.sechdrs, info.secstrings);
2552 2579
2553 err = check_module_license_and_versions(mod, sechdrs); 2580 err = check_module_license_and_versions(mod, info.sechdrs);
2554 if (err) 2581 if (err)
2555 goto free_unload; 2582 goto free_unload;
2556 2583
2557 /* Set up MODINFO_ATTR fields */ 2584 /* Set up MODINFO_ATTR fields */
2558 setup_modinfo(mod, sechdrs, infoindex); 2585 setup_modinfo(mod, info.sechdrs, info.index.info);
2559 2586
2560 /* Fix up syms, so that st_value is a pointer to location. */ 2587 /* Fix up syms, so that st_value is a pointer to location. */
2561 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex, 2588 err = simplify_symbols(info.sechdrs, info.index.sym, info.strtab, info.index.vers, info.index.pcpu,
2562 mod); 2589 mod);
2563 if (err < 0) 2590 if (err < 0)
2564 goto cleanup; 2591 goto cleanup;
2565 2592
2566 err = apply_relocations(mod, hdr, sechdrs, symindex, strindex); 2593 err = apply_relocations(mod, info.hdr, info.sechdrs, info.index.sym, info.index.str);
2567 if (err < 0) 2594 if (err < 0)
2568 goto cleanup; 2595 goto cleanup;
2569 2596
2570 /* Set up and sort exception table */ 2597 /* Set up and sort exception table */
2571 mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table", 2598 mod->extable = section_objs(info.hdr, info.sechdrs, info.secstrings, "__ex_table",
2572 sizeof(*mod->extable), &mod->num_exentries); 2599 sizeof(*mod->extable), &mod->num_exentries);
2573 sort_extable(mod->extable, mod->extable + mod->num_exentries); 2600 sort_extable(mod->extable, mod->extable + mod->num_exentries);
2574 2601
2575 /* Finally, copy percpu area over. */ 2602 /* Finally, copy percpu area over. */
2576 percpu_modcopy(mod, (void *)sechdrs[pcpuindex].sh_addr, 2603 percpu_modcopy(mod, (void *)info.sechdrs[info.index.pcpu].sh_addr,
2577 sechdrs[pcpuindex].sh_size); 2604 info.sechdrs[info.index.pcpu].sh_size);
2578 2605
2579 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, 2606 add_kallsyms(mod, info.sechdrs, info.hdr->e_shnum, info.index.sym, info.index.str,
2580 symoffs, stroffs, secstrings, strmap); 2607 symoffs, stroffs, info.secstrings, strmap);
2581 kfree(strmap); 2608 kfree(strmap);
2582 strmap = NULL; 2609 strmap = NULL;
2583 2610
2584 if (!mod->taints) 2611 if (!mod->taints)
2585 debug = section_objs(hdr, sechdrs, secstrings, "__verbose", 2612 debug = section_objs(info.hdr, info.sechdrs, info.secstrings, "__verbose",
2586 sizeof(*debug), &num_debug); 2613 sizeof(*debug), &num_debug);
2587 2614
2588 err = module_finalize(hdr, sechdrs, mod); 2615 err = module_finalize(info.hdr, info.sechdrs, mod);
2589 if (err < 0) 2616 if (err < 0)
2590 goto cleanup; 2617 goto cleanup;
2591 2618
2592 flush_module_icache(mod); 2619 flush_module_icache(mod);
2593 2620
2594 mod->args = args; 2621 mod->args = info.args;
2595 2622
2596 /* Now sew it into the lists so we can get lockdep and oops 2623 /* Now sew it into the lists so we can get lockdep and oops
2597 * info during argument parsing. Noone should access us, since 2624 * info during argument parsing. Noone should access us, since
@@ -2625,11 +2652,11 @@ static noinline struct module *load_module(void __user *umod,
2625 if (err < 0) 2652 if (err < 0)
2626 goto unlink; 2653 goto unlink;
2627 2654
2628 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 2655 add_sect_attrs(mod, info.hdr->e_shnum, info.secstrings, info.sechdrs);
2629 add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 2656 add_notes_attrs(mod, info.hdr->e_shnum, info.secstrings, info.sechdrs);
2630 2657
2631 /* Get rid of temporary copy */ 2658 /* Get rid of temporary copy */
2632 vfree(hdr); 2659 vfree(info.hdr);
2633 2660
2634 trace_module_load(mod); 2661 trace_module_load(mod);
2635 2662
@@ -2657,16 +2684,11 @@ static noinline struct module *load_module(void __user *umod,
2657 free_percpu: 2684 free_percpu:
2658 free_percpu(percpu); 2685 free_percpu(percpu);
2659 free_mod: 2686 free_mod:
2660 kfree(args); 2687 kfree(info.args);
2661 kfree(strmap); 2688 kfree(strmap);
2662 free_hdr: 2689 free_hdr:
2663 vfree(hdr); 2690 vfree(info.hdr);
2664 return ERR_PTR(err); 2691 return ERR_PTR(err);
2665
2666 truncated:
2667 printk(KERN_ERR "Module len %lu truncated\n", len);
2668 err = -ENOEXEC;
2669 goto free_hdr;
2670} 2692}
2671 2693
2672/* Call module constructors. */ 2694/* Call module constructors. */