aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-06-02 14:01:06 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-08-04 23:29:06 -0400
commit3264d3f9dd532ed9c3eb9491619e3f485b72747f (patch)
tree49a56f653c98578ef13c33a8fb6f7ba110517cf8 /kernel/module.c
parent44032e631691adf1f406843d5e54deb795973ff7 (diff)
module: add load_info
Btw, here's a patch that _looks_ large, but it really pretty trivial, and sets things up so that it would be way easier to split off pieces of the module loading. The reason it looks large is that it creates a "module_info" structure that contains all the module state that we're building up while loading, instead of having individual variables for all the indices etc. So the patch ends up being large, because every "symindex" access instead becomes "info.index.sym" etc. That may be a few characters longer, but it then means that we can just pass a pointer to that "info" structure around. and let all the pieces fill it in very naturally. As an example of that, the patch also moves the initialization of all those convenience variables into a "setup_module_info()" function. And at this point it really does become very natural to start to peel off some of the error labels and move them into the helper functions - now the "truncated" case is gone, and is handled inside that setup function instead. So maybe you don't like this approach, and it does make the variable accesses a bit longer, but I don't think unreadably so. And the patch really does look big and scary, but there really should be absolutely no semantic changes - most of it was a trivial and mindless rename. In fact, it was so mindless that I on purpose kept the existing helper functions looking like this: - err = check_modinfo(mod, sechdrs, infoindex, versindex); + err = check_modinfo(mod, info.sechdrs, info.index.info, info.index.vers); rather than changing them to just take the "info" pointer. IOW, a second phase (if you think the approach is ok) would change that calling convention to just do err = check_modinfo(mod, &info); (and same for "layout_sections()", "layout_symtabs()" etc.) Similarly, while right now it makes things _look_ bigger, with things like this: versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); becoming info->index.vers = find_sec(info->hdr, info->sechdrs, info->secstrings, "__versions"); in the new "setup_module_info()" function, that's again just a result of it being a search-and-replace patch. By using the 'info' pointer, we could just change the 'find_sec()' interface so that it ends up being info->index.vers = find_sec(info, "__versions"); instead, and then we'd actually have a shorter and more readable line. So for a lot of those mindless variable name expansions there's would be room for separate cleanups. I didn't move quite everything in there - if we do this to layout_symtabs, for example, we'd want to move the percpu, symoffs, stroffs, *strmap variables to be fields in that module_info structure too. But that's a much smaller patch, I moved just the really core stuff that is currently being set up and used in various parts. But even in this rough form, it removes close to 70 lines from that function (but adds 22 lines overall, of course - the structure definition, the helper function declarations and call-sites etc etc). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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. */