diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-09-14 00:16:56 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-09-14 00:16:56 -0400 |
| commit | fc8e1ead9314cf0e0f1922e661428b93d3a50d88 (patch) | |
| tree | f3cb97c4769b74f6627a59769f1ed5c92a13c58a /kernel/module.c | |
| parent | 2bcaa6a4238094c5695d5b1943078388d82d3004 (diff) | |
| parent | 9de48cc300fb10f7d9faa978670becf5e352462a (diff) | |
Merge branch 'next' into for-linus
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 126 |
1 files changed, 104 insertions, 22 deletions
diff --git a/kernel/module.c b/kernel/module.c index e797812a4d95..eccb561dd8a3 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | */ | 18 | */ |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/moduleloader.h> | 20 | #include <linux/moduleloader.h> |
| 21 | #include <linux/ftrace_event.h> | ||
| 21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 22 | #include <linux/kallsyms.h> | 23 | #include <linux/kallsyms.h> |
| 23 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| @@ -52,6 +53,7 @@ | |||
| 52 | #include <linux/ftrace.h> | 53 | #include <linux/ftrace.h> |
| 53 | #include <linux/async.h> | 54 | #include <linux/async.h> |
| 54 | #include <linux/percpu.h> | 55 | #include <linux/percpu.h> |
| 56 | #include <linux/kmemleak.h> | ||
| 55 | 57 | ||
| 56 | #if 0 | 58 | #if 0 |
| 57 | #define DEBUGP printk | 59 | #define DEBUGP printk |
| @@ -72,6 +74,9 @@ DEFINE_MUTEX(module_mutex); | |||
| 72 | EXPORT_SYMBOL_GPL(module_mutex); | 74 | EXPORT_SYMBOL_GPL(module_mutex); |
| 73 | static LIST_HEAD(modules); | 75 | static LIST_HEAD(modules); |
| 74 | 76 | ||
| 77 | /* Block module loading/unloading? */ | ||
| 78 | int modules_disabled = 0; | ||
| 79 | |||
| 75 | /* Waiting for a module to finish initializing? */ | 80 | /* Waiting for a module to finish initializing? */ |
| 76 | static DECLARE_WAIT_QUEUE_HEAD(module_wq); | 81 | static DECLARE_WAIT_QUEUE_HEAD(module_wq); |
| 77 | 82 | ||
| @@ -429,6 +434,7 @@ static void *percpu_modalloc(unsigned long size, unsigned long align, | |||
| 429 | unsigned long extra; | 434 | unsigned long extra; |
| 430 | unsigned int i; | 435 | unsigned int i; |
| 431 | void *ptr; | 436 | void *ptr; |
| 437 | int cpu; | ||
| 432 | 438 | ||
| 433 | if (align > PAGE_SIZE) { | 439 | if (align > PAGE_SIZE) { |
| 434 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", | 440 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", |
| @@ -458,6 +464,11 @@ static void *percpu_modalloc(unsigned long size, unsigned long align, | |||
| 458 | if (!split_block(i, size)) | 464 | if (!split_block(i, size)) |
| 459 | return NULL; | 465 | return NULL; |
| 460 | 466 | ||
| 467 | /* add the per-cpu scanning areas */ | ||
| 468 | for_each_possible_cpu(cpu) | ||
| 469 | kmemleak_alloc(ptr + per_cpu_offset(cpu), size, 0, | ||
| 470 | GFP_KERNEL); | ||
| 471 | |||
| 461 | /* Mark allocated */ | 472 | /* Mark allocated */ |
| 462 | pcpu_size[i] = -pcpu_size[i]; | 473 | pcpu_size[i] = -pcpu_size[i]; |
| 463 | return ptr; | 474 | return ptr; |
| @@ -472,6 +483,7 @@ static void percpu_modfree(void *freeme) | |||
| 472 | { | 483 | { |
| 473 | unsigned int i; | 484 | unsigned int i; |
| 474 | void *ptr = __per_cpu_start + block_size(pcpu_size[0]); | 485 | void *ptr = __per_cpu_start + block_size(pcpu_size[0]); |
| 486 | int cpu; | ||
| 475 | 487 | ||
| 476 | /* First entry is core kernel percpu data. */ | 488 | /* First entry is core kernel percpu data. */ |
| 477 | for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { | 489 | for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { |
| @@ -483,6 +495,10 @@ static void percpu_modfree(void *freeme) | |||
| 483 | BUG(); | 495 | BUG(); |
| 484 | 496 | ||
| 485 | free: | 497 | free: |
| 498 | /* remove the per-cpu scanning areas */ | ||
| 499 | for_each_possible_cpu(cpu) | ||
| 500 | kmemleak_free(freeme + per_cpu_offset(cpu)); | ||
| 501 | |||
| 486 | /* Merge with previous? */ | 502 | /* Merge with previous? */ |
| 487 | if (pcpu_size[i-1] >= 0) { | 503 | if (pcpu_size[i-1] >= 0) { |
| 488 | pcpu_size[i-1] += pcpu_size[i]; | 504 | pcpu_size[i-1] += pcpu_size[i]; |
| @@ -777,7 +793,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, | |||
| 777 | char name[MODULE_NAME_LEN]; | 793 | char name[MODULE_NAME_LEN]; |
| 778 | int ret, forced = 0; | 794 | int ret, forced = 0; |
| 779 | 795 | ||
| 780 | if (!capable(CAP_SYS_MODULE)) | 796 | if (!capable(CAP_SYS_MODULE) || modules_disabled) |
| 781 | return -EPERM; | 797 | return -EPERM; |
| 782 | 798 | ||
| 783 | if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) | 799 | if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) |
| @@ -893,16 +909,18 @@ void __symbol_put(const char *symbol) | |||
| 893 | } | 909 | } |
| 894 | EXPORT_SYMBOL(__symbol_put); | 910 | EXPORT_SYMBOL(__symbol_put); |
| 895 | 911 | ||
| 912 | /* Note this assumes addr is a function, which it currently always is. */ | ||
| 896 | void symbol_put_addr(void *addr) | 913 | void symbol_put_addr(void *addr) |
| 897 | { | 914 | { |
| 898 | struct module *modaddr; | 915 | struct module *modaddr; |
| 916 | unsigned long a = (unsigned long)dereference_function_descriptor(addr); | ||
| 899 | 917 | ||
| 900 | if (core_kernel_text((unsigned long)addr)) | 918 | if (core_kernel_text(a)) |
| 901 | return; | 919 | return; |
| 902 | 920 | ||
| 903 | /* module_text_address is safe here: we're supposed to have reference | 921 | /* module_text_address is safe here: we're supposed to have reference |
| 904 | * to module from symbol_get, so it can't go away. */ | 922 | * to module from symbol_get, so it can't go away. */ |
| 905 | modaddr = __module_text_address((unsigned long)addr); | 923 | modaddr = __module_text_address(a); |
| 906 | BUG_ON(!modaddr); | 924 | BUG_ON(!modaddr); |
| 907 | module_put(modaddr); | 925 | module_put(modaddr); |
| 908 | } | 926 | } |
| @@ -1052,7 +1070,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
| 1052 | { | 1070 | { |
| 1053 | const unsigned long *crc; | 1071 | const unsigned long *crc; |
| 1054 | 1072 | ||
| 1055 | if (!find_symbol("module_layout", NULL, &crc, true, false)) | 1073 | if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, |
| 1074 | &crc, true, false)) | ||
| 1056 | BUG(); | 1075 | BUG(); |
| 1057 | return check_version(sechdrs, versindex, "module_layout", mod, crc); | 1076 | return check_version(sechdrs, versindex, "module_layout", mod, crc); |
| 1058 | } | 1077 | } |
| @@ -1489,9 +1508,6 @@ static void free_module(struct module *mod) | |||
| 1489 | /* Free any allocated parameters. */ | 1508 | /* Free any allocated parameters. */ |
| 1490 | destroy_params(mod->kp, mod->num_kp); | 1509 | destroy_params(mod->kp, mod->num_kp); |
| 1491 | 1510 | ||
| 1492 | /* release any pointers to mcount in this module */ | ||
| 1493 | ftrace_release(mod->module_core, mod->core_size); | ||
| 1494 | |||
| 1495 | /* This may be NULL, but that's OK */ | 1511 | /* This may be NULL, but that's OK */ |
| 1496 | module_free(mod, mod->module_init); | 1512 | module_free(mod, mod->module_init); |
| 1497 | kfree(mod->args); | 1513 | kfree(mod->args); |
| @@ -1878,6 +1894,36 @@ static void *module_alloc_update_bounds(unsigned long size) | |||
| 1878 | return ret; | 1894 | return ret; |
| 1879 | } | 1895 | } |
| 1880 | 1896 | ||
| 1897 | #ifdef CONFIG_DEBUG_KMEMLEAK | ||
| 1898 | static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, | ||
| 1899 | Elf_Shdr *sechdrs, char *secstrings) | ||
| 1900 | { | ||
| 1901 | unsigned int i; | ||
| 1902 | |||
| 1903 | /* only scan the sections containing data */ | ||
| 1904 | kmemleak_scan_area(mod->module_core, (unsigned long)mod - | ||
| 1905 | (unsigned long)mod->module_core, | ||
| 1906 | sizeof(struct module), GFP_KERNEL); | ||
| 1907 | |||
| 1908 | for (i = 1; i < hdr->e_shnum; i++) { | ||
| 1909 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | ||
| 1910 | continue; | ||
| 1911 | if (strncmp(secstrings + sechdrs[i].sh_name, ".data", 5) != 0 | ||
| 1912 | && strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) != 0) | ||
| 1913 | continue; | ||
| 1914 | |||
| 1915 | kmemleak_scan_area(mod->module_core, sechdrs[i].sh_addr - | ||
| 1916 | (unsigned long)mod->module_core, | ||
| 1917 | sechdrs[i].sh_size, GFP_KERNEL); | ||
| 1918 | } | ||
| 1919 | } | ||
| 1920 | #else | ||
| 1921 | static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, | ||
| 1922 | Elf_Shdr *sechdrs, char *secstrings) | ||
| 1923 | { | ||
| 1924 | } | ||
| 1925 | #endif | ||
| 1926 | |||
| 1881 | /* Allocate and load the module: note that size of section 0 is always | 1927 | /* Allocate and load the module: note that size of section 0 is always |
| 1882 | zero, and we rely on this for optional sections. */ | 1928 | zero, and we rely on this for optional sections. */ |
| 1883 | static noinline struct module *load_module(void __user *umod, | 1929 | static noinline struct module *load_module(void __user *umod, |
| @@ -1892,11 +1938,9 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1892 | unsigned int symindex = 0; | 1938 | unsigned int symindex = 0; |
| 1893 | unsigned int strindex = 0; | 1939 | unsigned int strindex = 0; |
| 1894 | unsigned int modindex, versindex, infoindex, pcpuindex; | 1940 | unsigned int modindex, versindex, infoindex, pcpuindex; |
| 1895 | unsigned int num_mcount; | ||
| 1896 | struct module *mod; | 1941 | struct module *mod; |
| 1897 | long err = 0; | 1942 | long err = 0; |
| 1898 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 1943 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
| 1899 | unsigned long *mseg; | ||
| 1900 | mm_segment_t old_fs; | 1944 | mm_segment_t old_fs; |
| 1901 | 1945 | ||
| 1902 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", | 1946 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
| @@ -2050,6 +2094,12 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2050 | 2094 | ||
| 2051 | /* Do the allocs. */ | 2095 | /* Do the allocs. */ |
| 2052 | ptr = module_alloc_update_bounds(mod->core_size); | 2096 | ptr = module_alloc_update_bounds(mod->core_size); |
| 2097 | /* | ||
| 2098 | * The pointer to this block is stored in the module structure | ||
| 2099 | * which is inside the block. Just mark it as not being a | ||
| 2100 | * leak. | ||
| 2101 | */ | ||
| 2102 | kmemleak_not_leak(ptr); | ||
| 2053 | if (!ptr) { | 2103 | if (!ptr) { |
| 2054 | err = -ENOMEM; | 2104 | err = -ENOMEM; |
| 2055 | goto free_percpu; | 2105 | goto free_percpu; |
| @@ -2058,6 +2108,13 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2058 | mod->module_core = ptr; | 2108 | mod->module_core = ptr; |
| 2059 | 2109 | ||
| 2060 | ptr = module_alloc_update_bounds(mod->init_size); | 2110 | ptr = module_alloc_update_bounds(mod->init_size); |
| 2111 | /* | ||
| 2112 | * The pointer to this block is stored in the module structure | ||
| 2113 | * which is inside the block. This block doesn't need to be | ||
| 2114 | * scanned as it contains data and code that will be freed | ||
| 2115 | * after the module is initialized. | ||
| 2116 | */ | ||
| 2117 | kmemleak_ignore(ptr); | ||
| 2061 | if (!ptr && mod->init_size) { | 2118 | if (!ptr && mod->init_size) { |
| 2062 | err = -ENOMEM; | 2119 | err = -ENOMEM; |
| 2063 | goto free_core; | 2120 | goto free_core; |
| @@ -2088,6 +2145,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2088 | } | 2145 | } |
| 2089 | /* Module has been moved. */ | 2146 | /* Module has been moved. */ |
| 2090 | mod = (void *)sechdrs[modindex].sh_addr; | 2147 | mod = (void *)sechdrs[modindex].sh_addr; |
| 2148 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | ||
| 2091 | 2149 | ||
| 2092 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2150 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) |
| 2093 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | 2151 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), |
| @@ -2161,6 +2219,10 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2161 | mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings, | 2219 | mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings, |
| 2162 | "__kcrctab_unused_gpl"); | 2220 | "__kcrctab_unused_gpl"); |
| 2163 | #endif | 2221 | #endif |
| 2222 | #ifdef CONFIG_CONSTRUCTORS | ||
| 2223 | mod->ctors = section_objs(hdr, sechdrs, secstrings, ".ctors", | ||
| 2224 | sizeof(*mod->ctors), &mod->num_ctors); | ||
| 2225 | #endif | ||
| 2164 | 2226 | ||
| 2165 | #ifdef CONFIG_MARKERS | 2227 | #ifdef CONFIG_MARKERS |
| 2166 | mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers", | 2228 | mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers", |
| @@ -2172,7 +2234,19 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2172 | sizeof(*mod->tracepoints), | 2234 | sizeof(*mod->tracepoints), |
| 2173 | &mod->num_tracepoints); | 2235 | &mod->num_tracepoints); |
| 2174 | #endif | 2236 | #endif |
| 2175 | 2237 | #ifdef CONFIG_EVENT_TRACING | |
| 2238 | mod->trace_events = section_objs(hdr, sechdrs, secstrings, | ||
| 2239 | "_ftrace_events", | ||
| 2240 | sizeof(*mod->trace_events), | ||
| 2241 | &mod->num_trace_events); | ||
| 2242 | #endif | ||
| 2243 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD | ||
| 2244 | /* sechdrs[0].sh_size is always zero */ | ||
| 2245 | mod->ftrace_callsites = section_objs(hdr, sechdrs, secstrings, | ||
| 2246 | "__mcount_loc", | ||
| 2247 | sizeof(*mod->ftrace_callsites), | ||
| 2248 | &mod->num_ftrace_callsites); | ||
| 2249 | #endif | ||
| 2176 | #ifdef CONFIG_MODVERSIONS | 2250 | #ifdef CONFIG_MODVERSIONS |
| 2177 | if ((mod->num_syms && !mod->crcs) | 2251 | if ((mod->num_syms && !mod->crcs) |
| 2178 | || (mod->num_gpl_syms && !mod->gpl_crcs) | 2252 | || (mod->num_gpl_syms && !mod->gpl_crcs) |
| @@ -2237,11 +2311,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2237 | dynamic_debug_setup(debug, num_debug); | 2311 | dynamic_debug_setup(debug, num_debug); |
| 2238 | } | 2312 | } |
| 2239 | 2313 | ||
| 2240 | /* sechdrs[0].sh_size is always zero */ | ||
| 2241 | mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc", | ||
| 2242 | sizeof(*mseg), &num_mcount); | ||
| 2243 | ftrace_init_module(mod, mseg, mseg + num_mcount); | ||
| 2244 | |||
| 2245 | err = module_finalize(hdr, sechdrs, mod); | 2314 | err = module_finalize(hdr, sechdrs, mod); |
| 2246 | if (err < 0) | 2315 | if (err < 0) |
| 2247 | goto cleanup; | 2316 | goto cleanup; |
| @@ -2286,7 +2355,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2286 | if (err < 0) | 2355 | if (err < 0) |
| 2287 | goto unlink; | 2356 | goto unlink; |
| 2288 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2357 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
| 2289 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2358 | if (mod->sect_attrs) |
| 2359 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | ||
| 2290 | 2360 | ||
| 2291 | /* Get rid of temporary copy */ | 2361 | /* Get rid of temporary copy */ |
| 2292 | vfree(hdr); | 2362 | vfree(hdr); |
| @@ -2302,7 +2372,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2302 | cleanup: | 2372 | cleanup: |
| 2303 | kobject_del(&mod->mkobj.kobj); | 2373 | kobject_del(&mod->mkobj.kobj); |
| 2304 | kobject_put(&mod->mkobj.kobj); | 2374 | kobject_put(&mod->mkobj.kobj); |
| 2305 | ftrace_release(mod->module_core, mod->core_size); | ||
| 2306 | free_unload: | 2375 | free_unload: |
| 2307 | module_unload_free(mod); | 2376 | module_unload_free(mod); |
| 2308 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2377 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) |
| @@ -2328,6 +2397,17 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2328 | goto free_hdr; | 2397 | goto free_hdr; |
| 2329 | } | 2398 | } |
| 2330 | 2399 | ||
| 2400 | /* Call module constructors. */ | ||
| 2401 | static void do_mod_ctors(struct module *mod) | ||
| 2402 | { | ||
| 2403 | #ifdef CONFIG_CONSTRUCTORS | ||
| 2404 | unsigned long i; | ||
| 2405 | |||
| 2406 | for (i = 0; i < mod->num_ctors; i++) | ||
| 2407 | mod->ctors[i](); | ||
| 2408 | #endif | ||
| 2409 | } | ||
| 2410 | |||
| 2331 | /* This is where the real work happens */ | 2411 | /* This is where the real work happens */ |
| 2332 | SYSCALL_DEFINE3(init_module, void __user *, umod, | 2412 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
| 2333 | unsigned long, len, const char __user *, uargs) | 2413 | unsigned long, len, const char __user *, uargs) |
| @@ -2336,7 +2416,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2336 | int ret = 0; | 2416 | int ret = 0; |
| 2337 | 2417 | ||
| 2338 | /* Must have permission */ | 2418 | /* Must have permission */ |
| 2339 | if (!capable(CAP_SYS_MODULE)) | 2419 | if (!capable(CAP_SYS_MODULE) || modules_disabled) |
| 2340 | return -EPERM; | 2420 | return -EPERM; |
| 2341 | 2421 | ||
| 2342 | /* Only one module load at a time, please */ | 2422 | /* Only one module load at a time, please */ |
| @@ -2356,6 +2436,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2356 | blocking_notifier_call_chain(&module_notify_list, | 2436 | blocking_notifier_call_chain(&module_notify_list, |
| 2357 | MODULE_STATE_COMING, mod); | 2437 | MODULE_STATE_COMING, mod); |
| 2358 | 2438 | ||
| 2439 | do_mod_ctors(mod); | ||
| 2359 | /* Start the module */ | 2440 | /* Start the module */ |
| 2360 | if (mod->init != NULL) | 2441 | if (mod->init != NULL) |
| 2361 | ret = do_one_initcall(mod->init); | 2442 | ret = do_one_initcall(mod->init); |
| @@ -2374,9 +2455,9 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2374 | return ret; | 2455 | return ret; |
| 2375 | } | 2456 | } |
| 2376 | if (ret > 0) { | 2457 | if (ret > 0) { |
| 2377 | printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, " | 2458 | printk(KERN_WARNING |
| 2378 | "it should follow 0/-E convention\n" | 2459 | "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" |
| 2379 | KERN_WARNING "%s: loading module anyway...\n", | 2460 | "%s: loading module anyway...\n", |
| 2380 | __func__, mod->name, ret, | 2461 | __func__, mod->name, ret, |
| 2381 | __func__); | 2462 | __func__); |
| 2382 | dump_stack(); | 2463 | dump_stack(); |
| @@ -2394,6 +2475,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2394 | mutex_lock(&module_mutex); | 2475 | mutex_lock(&module_mutex); |
| 2395 | /* Drop initial reference. */ | 2476 | /* Drop initial reference. */ |
| 2396 | module_put(mod); | 2477 | module_put(mod); |
| 2478 | trim_init_extable(mod); | ||
| 2397 | module_free(mod, mod->module_init); | 2479 | module_free(mod, mod->module_init); |
| 2398 | mod->module_init = NULL; | 2480 | mod->module_init = NULL; |
| 2399 | mod->init_size = 0; | 2481 | mod->init_size = 0; |
| @@ -2837,7 +2919,7 @@ void print_modules(void) | |||
| 2837 | struct module *mod; | 2919 | struct module *mod; |
| 2838 | char buf[8]; | 2920 | char buf[8]; |
| 2839 | 2921 | ||
| 2840 | printk("Modules linked in:"); | 2922 | printk(KERN_DEFAULT "Modules linked in:"); |
| 2841 | /* Most callers should already have preempt disabled, but make sure */ | 2923 | /* Most callers should already have preempt disabled, but make sure */ |
| 2842 | preempt_disable(); | 2924 | preempt_disable(); |
| 2843 | list_for_each_entry_rcu(mod, &modules, list) | 2925 | list_for_each_entry_rcu(mod, &modules, list) |
