diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 228 |
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 | ||
2151 | static int copy_and_check(Elf_Ehdr **hdrp, | 2151 | struct 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 | |||
2161 | static 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 | ||
2186 | free_hdr: | 2197 | free_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 | */ | ||
2210 | static 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 | |||
2191 | static int check_modinfo(struct module *mod, | 2276 | static 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. */ |