Commit 65b8a9b4d5525348e55cf63a43517610ee8e0970

Authored by Linus Torvalds
Committed by Rusty Russell
1 parent f91a13bb99

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>

Showing 1 changed file with 72 additions and 57 deletions Side-by-side Diff

... ... @@ -2082,7 +2082,8 @@
2082 2082  
2083 2083 #ifdef CONFIG_DEBUG_KMEMLEAK
2084 2084 static 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 2088 unsigned int i;
2088 2089  
... ... @@ -2102,7 +2103,8 @@
2102 2103 }
2103 2104 #else
2104 2105 static 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 2110 #endif
... ... @@ -2172,6 +2174,70 @@
2172 2174 #endif
2173 2175 }
2174 2176  
  2177 +static 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 2241 /* Allocate and load the module: note that size of section 0 is always
2176 2242 zero, and we rely on this for optional sections. */
2177 2243 static noinline struct module *load_module(void __user *umod,
... ... @@ -2188,7 +2254,6 @@
2188 2254 unsigned int modindex, versindex, infoindex, pcpuindex;
2189 2255 struct module *mod;
2190 2256 long err = 0;
2191   - void *ptr = NULL; /* Stops spurious gcc warning */
2192 2257 unsigned long symoffs, stroffs, *strmap;
2193 2258 void __percpu *percpu;
2194 2259 struct _ddebug *debug = NULL;
2195 2260  
2196 2261  
... ... @@ -2342,62 +2407,13 @@
2342 2407 symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr,
2343 2408 secstrings, &stroffs, strmap);
2344 2409  
2345   - /* Do the allocs. */
2346   - ptr = module_alloc_update_bounds(mod->core_size);
2347   - /*
2348   - * The pointer to this block is stored in the module structure
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;
  2410 + /* Allocate and move to the final place */
  2411 + mod = move_module(mod, hdr, sechdrs, secstrings, modindex);
  2412 + if (IS_ERR(mod)) {
  2413 + err = PTR_ERR(mod);
2355 2414 goto free_percpu;
2356 2415 }
2357   - memset(ptr, 0, mod->core_size);
2358   - mod->module_core = ptr;
2359 2416  
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   -
2401 2417 #if defined(CONFIG_MODULE_UNLOAD)
2402 2418 mod->refptr = alloc_percpu(struct module_ref);
2403 2419 if (!mod->refptr) {
... ... @@ -2580,7 +2596,6 @@
2580 2596 free_init:
2581 2597 #endif
2582 2598 module_free(mod, mod->module_init);
2583   - free_core:
2584 2599 module_free(mod, mod->module_core);
2585 2600 /* mod will be freed with core. Don't access it beyond this line! */
2586 2601 free_percpu: