aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 14:59:02 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-08-04 23:29:03 -0400
commit65b8a9b4d5525348e55cf63a43517610ee8e0970 (patch)
tree1661d4bc368c768e803a1de4ddb0191bb71acab8 /kernel/module.c
parentf91a13bb99b73961d4e2743a6ff296ac553abc4f (diff)
module: refactor load_module part 2
Here's a second one. It's slightly less trivial - since we now have error cases - and equally untested so it may well be totally broken. But it also cleans up a bit more, and avoids one of the goto targets, because the "move_module()" helper now does both allocations or none. 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.c129
1 files changed, 72 insertions, 57 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 12905ed44393..19ddcb0dba36 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2082,7 +2082,8 @@ static void *module_alloc_update_bounds(unsigned long size)
2082 2082
2083#ifdef CONFIG_DEBUG_KMEMLEAK 2083#ifdef CONFIG_DEBUG_KMEMLEAK
2084static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, 2084static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
2085 Elf_Shdr *sechdrs, char *secstrings) 2085 const Elf_Shdr *sechdrs,
2086 const char *secstrings)
2086{ 2087{
2087 unsigned int i; 2088 unsigned int i;
2088 2089
@@ -2102,7 +2103,8 @@ static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
2102} 2103}
2103#else 2104#else
2104static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, 2105static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
2105 Elf_Shdr *sechdrs, char *secstrings) 2106 Elf_Shdr *sechdrs,
2107 const char *secstrings)
2106{ 2108{
2107} 2109}
2108#endif 2110#endif
@@ -2172,6 +2174,70 @@ static void find_module_sections(struct module *mod, Elf_Ehdr *hdr,
2172#endif 2174#endif
2173} 2175}
2174 2176
2177static struct module *move_module(struct module *mod,
2178 Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
2179 const char *secstrings, unsigned modindex)
2180{
2181 int i;
2182 void *ptr;
2183
2184 /* Do the allocs. */
2185 ptr = module_alloc_update_bounds(mod->core_size);
2186 /*
2187 * The pointer to this block is stored in the module structure
2188 * which is inside the block. Just mark it as not being a
2189 * leak.
2190 */
2191 kmemleak_not_leak(ptr);
2192 if (!ptr)
2193 return ERR_PTR(-ENOMEM);
2194
2195 memset(ptr, 0, mod->core_size);
2196 mod->module_core = ptr;
2197
2198 ptr = module_alloc_update_bounds(mod->init_size);
2199 /*
2200 * The pointer to this block is stored in the module structure
2201 * which is inside the block. This block doesn't need to be
2202 * scanned as it contains data and code that will be freed
2203 * after the module is initialized.
2204 */
2205 kmemleak_ignore(ptr);
2206 if (!ptr && mod->init_size) {
2207 module_free(mod, mod->module_core);
2208 return ERR_PTR(-ENOMEM);
2209 }
2210 memset(ptr, 0, mod->init_size);
2211 mod->module_init = ptr;
2212
2213 /* Transfer each section which specifies SHF_ALLOC */
2214 DEBUGP("final section addresses:\n");
2215 for (i = 0; i < hdr->e_shnum; i++) {
2216 void *dest;
2217
2218 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
2219 continue;
2220
2221 if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
2222 dest = mod->module_init
2223 + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
2224 else
2225 dest = mod->module_core + sechdrs[i].sh_entsize;
2226
2227 if (sechdrs[i].sh_type != SHT_NOBITS)
2228 memcpy(dest, (void *)sechdrs[i].sh_addr,
2229 sechdrs[i].sh_size);
2230 /* Update sh_addr to point to copy in image. */
2231 sechdrs[i].sh_addr = (unsigned long)dest;
2232 DEBUGP("\t0x%lx %s\n",
2233 sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
2234 }
2235 /* Module has been moved. */
2236 mod = (void *)sechdrs[modindex].sh_addr;
2237 kmemleak_load_module(mod, hdr, sechdrs, secstrings);
2238 return mod;
2239}
2240
2175/* Allocate and load the module: note that size of section 0 is always 2241/* Allocate and load the module: note that size of section 0 is always
2176 zero, and we rely on this for optional sections. */ 2242 zero, and we rely on this for optional sections. */
2177static noinline struct module *load_module(void __user *umod, 2243static noinline struct module *load_module(void __user *umod,
@@ -2188,7 +2254,6 @@ static noinline struct module *load_module(void __user *umod,
2188 unsigned int modindex, versindex, infoindex, pcpuindex; 2254 unsigned int modindex, versindex, infoindex, pcpuindex;
2189 struct module *mod; 2255 struct module *mod;
2190 long err = 0; 2256 long err = 0;
2191 void *ptr = NULL; /* Stops spurious gcc warning */
2192 unsigned long symoffs, stroffs, *strmap; 2257 unsigned long symoffs, stroffs, *strmap;
2193 void __percpu *percpu; 2258 void __percpu *percpu;
2194 struct _ddebug *debug = NULL; 2259 struct _ddebug *debug = NULL;
@@ -2342,61 +2407,12 @@ static noinline struct module *load_module(void __user *umod,
2342 symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr, 2407 symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr,
2343 secstrings, &stroffs, strmap); 2408 secstrings, &stroffs, strmap);
2344 2409
2345 /* Do the allocs. */ 2410 /* Allocate and move to the final place */
2346 ptr = module_alloc_update_bounds(mod->core_size); 2411 mod = move_module(mod, hdr, sechdrs, secstrings, modindex);
2347 /* 2412 if (IS_ERR(mod)) {
2348 * The pointer to this block is stored in the module structure 2413 err = PTR_ERR(mod);
2349 * which is inside the block. Just mark it as not being a
2350 * leak.
2351 */
2352 kmemleak_not_leak(ptr);
2353 if (!ptr) {
2354 err = -ENOMEM;
2355 goto free_percpu; 2414 goto free_percpu;
2356 } 2415 }
2357 memset(ptr, 0, mod->core_size);
2358 mod->module_core = ptr;
2359
2360 ptr = module_alloc_update_bounds(mod->init_size);
2361 /*
2362 * The pointer to this block is stored in the module structure
2363 * which is inside the block. This block doesn't need to be
2364 * scanned as it contains data and code that will be freed
2365 * after the module is initialized.
2366 */
2367 kmemleak_ignore(ptr);
2368 if (!ptr && mod->init_size) {
2369 err = -ENOMEM;
2370 goto free_core;
2371 }
2372 memset(ptr, 0, mod->init_size);
2373 mod->module_init = ptr;
2374
2375 /* Transfer each section which specifies SHF_ALLOC */
2376 DEBUGP("final section addresses:\n");
2377 for (i = 0; i < hdr->e_shnum; i++) {
2378 void *dest;
2379
2380 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
2381 continue;
2382
2383 if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
2384 dest = mod->module_init
2385 + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
2386 else
2387 dest = mod->module_core + sechdrs[i].sh_entsize;
2388
2389 if (sechdrs[i].sh_type != SHT_NOBITS)
2390 memcpy(dest, (void *)sechdrs[i].sh_addr,
2391 sechdrs[i].sh_size);
2392 /* Update sh_addr to point to copy in image. */
2393 sechdrs[i].sh_addr = (unsigned long)dest;
2394 DEBUGP("\t0x%lx %s\n",
2395 sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
2396 }
2397 /* Module has been moved. */
2398 mod = (void *)sechdrs[modindex].sh_addr;
2399 kmemleak_load_module(mod, hdr, sechdrs, secstrings);
2400 2416
2401#if defined(CONFIG_MODULE_UNLOAD) 2417#if defined(CONFIG_MODULE_UNLOAD)
2402 mod->refptr = alloc_percpu(struct module_ref); 2418 mod->refptr = alloc_percpu(struct module_ref);
@@ -2580,7 +2596,6 @@ static noinline struct module *load_module(void __user *umod,
2580 free_init: 2596 free_init:
2581#endif 2597#endif
2582 module_free(mod, mod->module_init); 2598 module_free(mod, mod->module_init);
2583 free_core:
2584 module_free(mod, mod->module_core); 2599 module_free(mod, mod->module_core);
2585 /* mod will be freed with core. Don't access it beyond this line! */ 2600 /* mod will be freed with core. Don't access it beyond this line! */
2586 free_percpu: 2601 free_percpu: