diff options
| -rw-r--r-- | arch/avr32/kernel/module.c | 13 | ||||
| -rw-r--r-- | arch/cris/kernel/module.c | 2 | ||||
| -rw-r--r-- | arch/ia64/kernel/module.c | 6 | ||||
| -rw-r--r-- | arch/mips/net/bpf_jit.c | 2 | ||||
| -rw-r--r-- | arch/nios2/kernel/module.c | 2 | ||||
| -rw-r--r-- | arch/parisc/kernel/module.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/net/bpf_jit_comp.c | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/module.c | 10 | ||||
| -rw-r--r-- | arch/sparc/net/bpf_jit_comp.c | 4 | ||||
| -rw-r--r-- | arch/tile/kernel/module.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/ftrace.c | 2 | ||||
| -rw-r--r-- | include/linux/module.h | 2 | ||||
| -rw-r--r-- | include/linux/moduleloader.h | 4 | ||||
| -rw-r--r-- | kernel/bpf/core.c | 2 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_main.c | 2 | ||||
| -rw-r--r-- | kernel/kprobes.c | 2 | ||||
| -rw-r--r-- | kernel/module.c | 91 | ||||
| -rw-r--r-- | kernel/params.c | 3 |
18 files changed, 94 insertions, 65 deletions
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index 2c9412908024..164efa009e5b 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c | |||
| @@ -19,12 +19,10 @@ | |||
| 19 | #include <linux/moduleloader.h> | 19 | #include <linux/moduleloader.h> |
| 20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
| 21 | 21 | ||
| 22 | void module_free(struct module *mod, void *module_region) | 22 | void module_arch_freeing_init(struct module *mod) |
| 23 | { | 23 | { |
| 24 | vfree(mod->arch.syminfo); | 24 | vfree(mod->arch.syminfo); |
| 25 | mod->arch.syminfo = NULL; | 25 | mod->arch.syminfo = NULL; |
| 26 | |||
| 27 | vfree(module_region); | ||
| 28 | } | 26 | } |
| 29 | 27 | ||
| 30 | static inline int check_rela(Elf32_Rela *rela, struct module *module, | 28 | static inline int check_rela(Elf32_Rela *rela, struct module *module, |
| @@ -291,12 +289,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, | |||
| 291 | 289 | ||
| 292 | return ret; | 290 | return ret; |
| 293 | } | 291 | } |
| 294 | |||
| 295 | int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
| 296 | struct module *module) | ||
| 297 | { | ||
| 298 | vfree(module->arch.syminfo); | ||
| 299 | module->arch.syminfo = NULL; | ||
| 300 | |||
| 301 | return 0; | ||
| 302 | } | ||
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c index 51123f985eb5..af04cb6b6dc9 100644 --- a/arch/cris/kernel/module.c +++ b/arch/cris/kernel/module.c | |||
| @@ -36,7 +36,7 @@ void *module_alloc(unsigned long size) | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | /* Free memory returned from module_alloc */ | 38 | /* Free memory returned from module_alloc */ |
| 39 | void module_free(struct module *mod, void *module_region) | 39 | void module_memfree(void *module_region) |
| 40 | { | 40 | { |
| 41 | kfree(module_region); | 41 | kfree(module_region); |
| 42 | } | 42 | } |
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 24603be24c14..29754aae5177 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c | |||
| @@ -305,14 +305,12 @@ plt_target (struct plt_entry *plt) | |||
| 305 | #endif /* !USE_BRL */ | 305 | #endif /* !USE_BRL */ |
| 306 | 306 | ||
| 307 | void | 307 | void |
| 308 | module_free (struct module *mod, void *module_region) | 308 | module_arch_freeing_init (struct module *mod) |
| 309 | { | 309 | { |
| 310 | if (mod && mod->arch.init_unw_table && | 310 | if (mod->arch.init_unw_table) { |
| 311 | module_region == mod->module_init) { | ||
| 312 | unw_remove_unwind_table(mod->arch.init_unw_table); | 311 | unw_remove_unwind_table(mod->arch.init_unw_table); |
| 313 | mod->arch.init_unw_table = NULL; | 312 | mod->arch.init_unw_table = NULL; |
| 314 | } | 313 | } |
| 315 | vfree(module_region); | ||
| 316 | } | 314 | } |
| 317 | 315 | ||
| 318 | /* Have we already seen one of these relocations? */ | 316 | /* Have we already seen one of these relocations? */ |
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 9fd6834a2172..5d6139390bf8 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c | |||
| @@ -1388,7 +1388,7 @@ out: | |||
| 1388 | void bpf_jit_free(struct bpf_prog *fp) | 1388 | void bpf_jit_free(struct bpf_prog *fp) |
| 1389 | { | 1389 | { |
| 1390 | if (fp->jited) | 1390 | if (fp->jited) |
| 1391 | module_free(NULL, fp->bpf_func); | 1391 | module_memfree(fp->bpf_func); |
| 1392 | 1392 | ||
| 1393 | bpf_prog_unlock_free(fp); | 1393 | bpf_prog_unlock_free(fp); |
| 1394 | } | 1394 | } |
diff --git a/arch/nios2/kernel/module.c b/arch/nios2/kernel/module.c index cc924a38f22a..e2e3f13f98d5 100644 --- a/arch/nios2/kernel/module.c +++ b/arch/nios2/kernel/module.c | |||
| @@ -36,7 +36,7 @@ void *module_alloc(unsigned long size) | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | /* Free memory returned from module_alloc */ | 38 | /* Free memory returned from module_alloc */ |
| 39 | void module_free(struct module *mod, void *module_region) | 39 | void module_memfree(void *module_region) |
| 40 | { | 40 | { |
| 41 | kfree(module_region); | 41 | kfree(module_region); |
| 42 | } | 42 | } |
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 50dfafc3f2c1..5822e8e200e6 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
| @@ -298,14 +298,10 @@ static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) | |||
| 298 | } | 298 | } |
| 299 | #endif | 299 | #endif |
| 300 | 300 | ||
| 301 | 301 | void module_arch_freeing_init(struct module *mod) | |
| 302 | /* Free memory returned from module_alloc */ | ||
| 303 | void module_free(struct module *mod, void *module_region) | ||
| 304 | { | 302 | { |
| 305 | kfree(mod->arch.section); | 303 | kfree(mod->arch.section); |
| 306 | mod->arch.section = NULL; | 304 | mod->arch.section = NULL; |
| 307 | |||
| 308 | vfree(module_region); | ||
| 309 | } | 305 | } |
| 310 | 306 | ||
| 311 | /* Additional bytes needed in front of individual sections */ | 307 | /* Additional bytes needed in front of individual sections */ |
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 1ca125b9c226..d1916b577f2c 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c | |||
| @@ -699,7 +699,7 @@ out: | |||
| 699 | void bpf_jit_free(struct bpf_prog *fp) | 699 | void bpf_jit_free(struct bpf_prog *fp) |
| 700 | { | 700 | { |
| 701 | if (fp->jited) | 701 | if (fp->jited) |
| 702 | module_free(NULL, fp->bpf_func); | 702 | module_memfree(fp->bpf_func); |
| 703 | 703 | ||
| 704 | bpf_prog_unlock_free(fp); | 704 | bpf_prog_unlock_free(fp); |
| 705 | } | 705 | } |
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index b89b59158b95..409d152585be 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c | |||
| @@ -55,14 +55,10 @@ void *module_alloc(unsigned long size) | |||
| 55 | } | 55 | } |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | /* Free memory returned from module_alloc */ | 58 | void module_arch_freeing_init(struct module *mod) |
| 59 | void module_free(struct module *mod, void *module_region) | ||
| 60 | { | 59 | { |
| 61 | if (mod) { | 60 | vfree(mod->arch.syminfo); |
| 62 | vfree(mod->arch.syminfo); | 61 | mod->arch.syminfo = NULL; |
| 63 | mod->arch.syminfo = NULL; | ||
| 64 | } | ||
| 65 | vfree(module_region); | ||
| 66 | } | 62 | } |
| 67 | 63 | ||
| 68 | static void check_rela(Elf_Rela *rela, struct module *me) | 64 | static void check_rela(Elf_Rela *rela, struct module *me) |
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index f33e7c7a3bf7..7931eeeb649a 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c | |||
| @@ -776,7 +776,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf]; | |||
| 776 | if (unlikely(proglen + ilen > oldproglen)) { | 776 | if (unlikely(proglen + ilen > oldproglen)) { |
| 777 | pr_err("bpb_jit_compile fatal error\n"); | 777 | pr_err("bpb_jit_compile fatal error\n"); |
| 778 | kfree(addrs); | 778 | kfree(addrs); |
| 779 | module_free(NULL, image); | 779 | module_memfree(image); |
| 780 | return; | 780 | return; |
| 781 | } | 781 | } |
| 782 | memcpy(image + proglen, temp, ilen); | 782 | memcpy(image + proglen, temp, ilen); |
| @@ -822,7 +822,7 @@ out: | |||
| 822 | void bpf_jit_free(struct bpf_prog *fp) | 822 | void bpf_jit_free(struct bpf_prog *fp) |
| 823 | { | 823 | { |
| 824 | if (fp->jited) | 824 | if (fp->jited) |
| 825 | module_free(NULL, fp->bpf_func); | 825 | module_memfree(fp->bpf_func); |
| 826 | 826 | ||
| 827 | bpf_prog_unlock_free(fp); | 827 | bpf_prog_unlock_free(fp); |
| 828 | } | 828 | } |
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index 96447c9160a0..2305084c9b93 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c | |||
| @@ -74,7 +74,7 @@ error: | |||
| 74 | 74 | ||
| 75 | 75 | ||
| 76 | /* Free memory returned from module_alloc */ | 76 | /* Free memory returned from module_alloc */ |
| 77 | void module_free(struct module *mod, void *module_region) | 77 | void module_memfree(void *module_region) |
| 78 | { | 78 | { |
| 79 | vfree(module_region); | 79 | vfree(module_region); |
| 80 | 80 | ||
| @@ -83,7 +83,7 @@ void module_free(struct module *mod, void *module_region) | |||
| 83 | 0, 0, 0, NULL, NULL, 0); | 83 | 0, 0, 0, NULL, NULL, 0); |
| 84 | 84 | ||
| 85 | /* | 85 | /* |
| 86 | * FIXME: If module_region == mod->module_init, trim exception | 86 | * FIXME: Add module_arch_freeing_init to trim exception |
| 87 | * table entries. | 87 | * table entries. |
| 88 | */ | 88 | */ |
| 89 | } | 89 | } |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 2142376dc8c6..8b7b0a51e742 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
| @@ -674,7 +674,7 @@ static inline void *alloc_tramp(unsigned long size) | |||
| 674 | } | 674 | } |
| 675 | static inline void tramp_free(void *tramp) | 675 | static inline void tramp_free(void *tramp) |
| 676 | { | 676 | { |
| 677 | module_free(NULL, tramp); | 677 | module_memfree(tramp); |
| 678 | } | 678 | } |
| 679 | #else | 679 | #else |
| 680 | /* Trampolines can only be created if modules are supported */ | 680 | /* Trampolines can only be created if modules are supported */ |
diff --git a/include/linux/module.h b/include/linux/module.h index ebfb0e153c6a..b653d7c0a05a 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -444,7 +444,7 @@ extern void __module_put_and_exit(struct module *mod, long code) | |||
| 444 | #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code) | 444 | #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code) |
| 445 | 445 | ||
| 446 | #ifdef CONFIG_MODULE_UNLOAD | 446 | #ifdef CONFIG_MODULE_UNLOAD |
| 447 | unsigned long module_refcount(struct module *mod); | 447 | int module_refcount(struct module *mod); |
| 448 | void __symbol_put(const char *symbol); | 448 | void __symbol_put(const char *symbol); |
| 449 | #define symbol_put(x) __symbol_put(VMLINUX_SYMBOL_STR(x)) | 449 | #define symbol_put(x) __symbol_put(VMLINUX_SYMBOL_STR(x)) |
| 450 | void symbol_put_addr(void *addr); | 450 | void symbol_put_addr(void *addr); |
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h index 7eeb9bbfb816..f7556261fe3c 100644 --- a/include/linux/moduleloader.h +++ b/include/linux/moduleloader.h | |||
| @@ -26,7 +26,7 @@ unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section); | |||
| 26 | void *module_alloc(unsigned long size); | 26 | void *module_alloc(unsigned long size); |
| 27 | 27 | ||
| 28 | /* Free memory returned from module_alloc. */ | 28 | /* Free memory returned from module_alloc. */ |
| 29 | void module_free(struct module *mod, void *module_region); | 29 | void module_memfree(void *module_region); |
| 30 | 30 | ||
| 31 | /* | 31 | /* |
| 32 | * Apply the given relocation to the (simplified) ELF. Return -error | 32 | * Apply the given relocation to the (simplified) ELF. Return -error |
| @@ -82,4 +82,6 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
| 82 | /* Any cleanup needed when module leaves. */ | 82 | /* Any cleanup needed when module leaves. */ |
| 83 | void module_arch_cleanup(struct module *mod); | 83 | void module_arch_cleanup(struct module *mod); |
| 84 | 84 | ||
| 85 | /* Any cleanup before freeing mod->module_init */ | ||
| 86 | void module_arch_freeing_init(struct module *mod); | ||
| 85 | #endif | 87 | #endif |
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index d6594e457a25..a64e7a207d2b 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c | |||
| @@ -163,7 +163,7 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, | |||
| 163 | 163 | ||
| 164 | void bpf_jit_binary_free(struct bpf_binary_header *hdr) | 164 | void bpf_jit_binary_free(struct bpf_binary_header *hdr) |
| 165 | { | 165 | { |
| 166 | module_free(NULL, hdr); | 166 | module_memfree(hdr); |
| 167 | } | 167 | } |
| 168 | #endif /* CONFIG_BPF_JIT */ | 168 | #endif /* CONFIG_BPF_JIT */ |
| 169 | 169 | ||
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index f191bddf64b8..7b40c5f07dce 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
| @@ -2023,7 +2023,7 @@ static int kdb_lsmod(int argc, const char **argv) | |||
| 2023 | kdb_printf("%-20s%8u 0x%p ", mod->name, | 2023 | kdb_printf("%-20s%8u 0x%p ", mod->name, |
| 2024 | mod->core_size, (void *)mod); | 2024 | mod->core_size, (void *)mod); |
| 2025 | #ifdef CONFIG_MODULE_UNLOAD | 2025 | #ifdef CONFIG_MODULE_UNLOAD |
| 2026 | kdb_printf("%4ld ", module_refcount(mod)); | 2026 | kdb_printf("%4d ", module_refcount(mod)); |
| 2027 | #endif | 2027 | #endif |
| 2028 | if (mod->state == MODULE_STATE_GOING) | 2028 | if (mod->state == MODULE_STATE_GOING) |
| 2029 | kdb_printf(" (Unloading)"); | 2029 | kdb_printf(" (Unloading)"); |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 06f58309fed2..ee619929cf90 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -127,7 +127,7 @@ static void *alloc_insn_page(void) | |||
| 127 | 127 | ||
| 128 | static void free_insn_page(void *page) | 128 | static void free_insn_page(void *page) |
| 129 | { | 129 | { |
| 130 | module_free(NULL, page); | 130 | module_memfree(page); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | struct kprobe_insn_cache kprobe_insn_slots = { | 133 | struct kprobe_insn_cache kprobe_insn_slots = { |
diff --git a/kernel/module.c b/kernel/module.c index 3965511ae133..d856e96a3cce 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -772,9 +772,18 @@ static int try_stop_module(struct module *mod, int flags, int *forced) | |||
| 772 | return 0; | 772 | return 0; |
| 773 | } | 773 | } |
| 774 | 774 | ||
| 775 | unsigned long module_refcount(struct module *mod) | 775 | /** |
| 776 | * module_refcount - return the refcount or -1 if unloading | ||
| 777 | * | ||
| 778 | * @mod: the module we're checking | ||
| 779 | * | ||
| 780 | * Returns: | ||
| 781 | * -1 if the module is in the process of unloading | ||
| 782 | * otherwise the number of references in the kernel to the module | ||
| 783 | */ | ||
| 784 | int module_refcount(struct module *mod) | ||
| 776 | { | 785 | { |
| 777 | return (unsigned long)atomic_read(&mod->refcnt) - MODULE_REF_BASE; | 786 | return atomic_read(&mod->refcnt) - MODULE_REF_BASE; |
| 778 | } | 787 | } |
| 779 | EXPORT_SYMBOL(module_refcount); | 788 | EXPORT_SYMBOL(module_refcount); |
| 780 | 789 | ||
| @@ -856,7 +865,7 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod) | |||
| 856 | struct module_use *use; | 865 | struct module_use *use; |
| 857 | int printed_something = 0; | 866 | int printed_something = 0; |
| 858 | 867 | ||
| 859 | seq_printf(m, " %lu ", module_refcount(mod)); | 868 | seq_printf(m, " %i ", module_refcount(mod)); |
| 860 | 869 | ||
| 861 | /* | 870 | /* |
| 862 | * Always include a trailing , so userspace can differentiate | 871 | * Always include a trailing , so userspace can differentiate |
| @@ -908,7 +917,7 @@ EXPORT_SYMBOL_GPL(symbol_put_addr); | |||
| 908 | static ssize_t show_refcnt(struct module_attribute *mattr, | 917 | static ssize_t show_refcnt(struct module_attribute *mattr, |
| 909 | struct module_kobject *mk, char *buffer) | 918 | struct module_kobject *mk, char *buffer) |
| 910 | { | 919 | { |
| 911 | return sprintf(buffer, "%lu\n", module_refcount(mk->mod)); | 920 | return sprintf(buffer, "%i\n", module_refcount(mk->mod)); |
| 912 | } | 921 | } |
| 913 | 922 | ||
| 914 | static struct module_attribute modinfo_refcnt = | 923 | static struct module_attribute modinfo_refcnt = |
| @@ -1795,7 +1804,7 @@ static void unset_module_core_ro_nx(struct module *mod) { } | |||
| 1795 | static void unset_module_init_ro_nx(struct module *mod) { } | 1804 | static void unset_module_init_ro_nx(struct module *mod) { } |
| 1796 | #endif | 1805 | #endif |
| 1797 | 1806 | ||
| 1798 | void __weak module_free(struct module *mod, void *module_region) | 1807 | void __weak module_memfree(void *module_region) |
| 1799 | { | 1808 | { |
| 1800 | vfree(module_region); | 1809 | vfree(module_region); |
| 1801 | } | 1810 | } |
| @@ -1804,6 +1813,10 @@ void __weak module_arch_cleanup(struct module *mod) | |||
| 1804 | { | 1813 | { |
| 1805 | } | 1814 | } |
| 1806 | 1815 | ||
| 1816 | void __weak module_arch_freeing_init(struct module *mod) | ||
| 1817 | { | ||
| 1818 | } | ||
| 1819 | |||
| 1807 | /* Free a module, remove from lists, etc. */ | 1820 | /* Free a module, remove from lists, etc. */ |
| 1808 | static void free_module(struct module *mod) | 1821 | static void free_module(struct module *mod) |
| 1809 | { | 1822 | { |
| @@ -1841,7 +1854,8 @@ static void free_module(struct module *mod) | |||
| 1841 | 1854 | ||
| 1842 | /* This may be NULL, but that's OK */ | 1855 | /* This may be NULL, but that's OK */ |
| 1843 | unset_module_init_ro_nx(mod); | 1856 | unset_module_init_ro_nx(mod); |
| 1844 | module_free(mod, mod->module_init); | 1857 | module_arch_freeing_init(mod); |
| 1858 | module_memfree(mod->module_init); | ||
| 1845 | kfree(mod->args); | 1859 | kfree(mod->args); |
| 1846 | percpu_modfree(mod); | 1860 | percpu_modfree(mod); |
| 1847 | 1861 | ||
| @@ -1850,7 +1864,7 @@ static void free_module(struct module *mod) | |||
| 1850 | 1864 | ||
| 1851 | /* Finally, free the core (containing the module structure) */ | 1865 | /* Finally, free the core (containing the module structure) */ |
| 1852 | unset_module_core_ro_nx(mod); | 1866 | unset_module_core_ro_nx(mod); |
| 1853 | module_free(mod, mod->module_core); | 1867 | module_memfree(mod->module_core); |
| 1854 | 1868 | ||
| 1855 | #ifdef CONFIG_MPU | 1869 | #ifdef CONFIG_MPU |
| 1856 | update_protections(current->mm); | 1870 | update_protections(current->mm); |
| @@ -2785,7 +2799,7 @@ static int move_module(struct module *mod, struct load_info *info) | |||
| 2785 | */ | 2799 | */ |
| 2786 | kmemleak_ignore(ptr); | 2800 | kmemleak_ignore(ptr); |
| 2787 | if (!ptr) { | 2801 | if (!ptr) { |
| 2788 | module_free(mod, mod->module_core); | 2802 | module_memfree(mod->module_core); |
| 2789 | return -ENOMEM; | 2803 | return -ENOMEM; |
| 2790 | } | 2804 | } |
| 2791 | memset(ptr, 0, mod->init_size); | 2805 | memset(ptr, 0, mod->init_size); |
| @@ -2930,8 +2944,9 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
| 2930 | static void module_deallocate(struct module *mod, struct load_info *info) | 2944 | static void module_deallocate(struct module *mod, struct load_info *info) |
| 2931 | { | 2945 | { |
| 2932 | percpu_modfree(mod); | 2946 | percpu_modfree(mod); |
| 2933 | module_free(mod, mod->module_init); | 2947 | module_arch_freeing_init(mod); |
| 2934 | module_free(mod, mod->module_core); | 2948 | module_memfree(mod->module_init); |
| 2949 | module_memfree(mod->module_core); | ||
| 2935 | } | 2950 | } |
| 2936 | 2951 | ||
| 2937 | int __weak module_finalize(const Elf_Ehdr *hdr, | 2952 | int __weak module_finalize(const Elf_Ehdr *hdr, |
| @@ -2983,10 +2998,31 @@ static void do_mod_ctors(struct module *mod) | |||
| 2983 | #endif | 2998 | #endif |
| 2984 | } | 2999 | } |
| 2985 | 3000 | ||
| 3001 | /* For freeing module_init on success, in case kallsyms traversing */ | ||
| 3002 | struct mod_initfree { | ||
| 3003 | struct rcu_head rcu; | ||
| 3004 | void *module_init; | ||
| 3005 | }; | ||
| 3006 | |||
| 3007 | static void do_free_init(struct rcu_head *head) | ||
| 3008 | { | ||
| 3009 | struct mod_initfree *m = container_of(head, struct mod_initfree, rcu); | ||
| 3010 | module_memfree(m->module_init); | ||
| 3011 | kfree(m); | ||
| 3012 | } | ||
| 3013 | |||
| 2986 | /* This is where the real work happens */ | 3014 | /* This is where the real work happens */ |
| 2987 | static int do_init_module(struct module *mod) | 3015 | static int do_init_module(struct module *mod) |
| 2988 | { | 3016 | { |
| 2989 | int ret = 0; | 3017 | int ret = 0; |
| 3018 | struct mod_initfree *freeinit; | ||
| 3019 | |||
| 3020 | freeinit = kmalloc(sizeof(*freeinit), GFP_KERNEL); | ||
| 3021 | if (!freeinit) { | ||
| 3022 | ret = -ENOMEM; | ||
| 3023 | goto fail; | ||
| 3024 | } | ||
| 3025 | freeinit->module_init = mod->module_init; | ||
| 2990 | 3026 | ||
| 2991 | /* | 3027 | /* |
| 2992 | * We want to find out whether @mod uses async during init. Clear | 3028 | * We want to find out whether @mod uses async during init. Clear |
| @@ -2999,18 +3035,7 @@ static int do_init_module(struct module *mod) | |||
| 2999 | if (mod->init != NULL) | 3035 | if (mod->init != NULL) |
| 3000 | ret = do_one_initcall(mod->init); | 3036 | ret = do_one_initcall(mod->init); |
| 3001 | if (ret < 0) { | 3037 | if (ret < 0) { |
| 3002 | /* | 3038 | goto fail_free_freeinit; |
| 3003 | * Init routine failed: abort. Try to protect us from | ||
| 3004 | * buggy refcounters. | ||
| 3005 | */ | ||
| 3006 | mod->state = MODULE_STATE_GOING; | ||
| 3007 | synchronize_sched(); | ||
| 3008 | module_put(mod); | ||
| 3009 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3010 | MODULE_STATE_GOING, mod); | ||
| 3011 | free_module(mod); | ||
| 3012 | wake_up_all(&module_wq); | ||
| 3013 | return ret; | ||
| 3014 | } | 3039 | } |
| 3015 | if (ret > 0) { | 3040 | if (ret > 0) { |
| 3016 | pr_warn("%s: '%s'->init suspiciously returned %d, it should " | 3041 | pr_warn("%s: '%s'->init suspiciously returned %d, it should " |
| @@ -3055,15 +3080,35 @@ static int do_init_module(struct module *mod) | |||
| 3055 | mod->strtab = mod->core_strtab; | 3080 | mod->strtab = mod->core_strtab; |
| 3056 | #endif | 3081 | #endif |
| 3057 | unset_module_init_ro_nx(mod); | 3082 | unset_module_init_ro_nx(mod); |
| 3058 | module_free(mod, mod->module_init); | 3083 | module_arch_freeing_init(mod); |
| 3059 | mod->module_init = NULL; | 3084 | mod->module_init = NULL; |
| 3060 | mod->init_size = 0; | 3085 | mod->init_size = 0; |
| 3061 | mod->init_ro_size = 0; | 3086 | mod->init_ro_size = 0; |
| 3062 | mod->init_text_size = 0; | 3087 | mod->init_text_size = 0; |
| 3088 | /* | ||
| 3089 | * We want to free module_init, but be aware that kallsyms may be | ||
| 3090 | * walking this with preempt disabled. In all the failure paths, | ||
| 3091 | * we call synchronize_rcu/synchronize_sched, but we don't want | ||
| 3092 | * to slow down the success path, so use actual RCU here. | ||
| 3093 | */ | ||
| 3094 | call_rcu(&freeinit->rcu, do_free_init); | ||
| 3063 | mutex_unlock(&module_mutex); | 3095 | mutex_unlock(&module_mutex); |
| 3064 | wake_up_all(&module_wq); | 3096 | wake_up_all(&module_wq); |
| 3065 | 3097 | ||
| 3066 | return 0; | 3098 | return 0; |
| 3099 | |||
| 3100 | fail_free_freeinit: | ||
| 3101 | kfree(freeinit); | ||
| 3102 | fail: | ||
| 3103 | /* Try to protect us from buggy refcounters. */ | ||
| 3104 | mod->state = MODULE_STATE_GOING; | ||
| 3105 | synchronize_sched(); | ||
| 3106 | module_put(mod); | ||
| 3107 | blocking_notifier_call_chain(&module_notify_list, | ||
| 3108 | MODULE_STATE_GOING, mod); | ||
| 3109 | free_module(mod); | ||
| 3110 | wake_up_all(&module_wq); | ||
| 3111 | return ret; | ||
| 3067 | } | 3112 | } |
| 3068 | 3113 | ||
| 3069 | static int may_init_module(void) | 3114 | static int may_init_module(void) |
diff --git a/kernel/params.c b/kernel/params.c index 0af9b2c4e56c..728e05b167de 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -642,12 +642,15 @@ static __modinit int add_sysfs_param(struct module_kobject *mk, | |||
| 642 | mk->mp->grp.attrs = new_attrs; | 642 | mk->mp->grp.attrs = new_attrs; |
| 643 | 643 | ||
| 644 | /* Tack new one on the end. */ | 644 | /* Tack new one on the end. */ |
| 645 | memset(&mk->mp->attrs[mk->mp->num], 0, sizeof(mk->mp->attrs[0])); | ||
| 645 | sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr); | 646 | sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr); |
| 646 | mk->mp->attrs[mk->mp->num].param = kp; | 647 | mk->mp->attrs[mk->mp->num].param = kp; |
| 647 | mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show; | 648 | mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show; |
| 648 | /* Do not allow runtime DAC changes to make param writable. */ | 649 | /* Do not allow runtime DAC changes to make param writable. */ |
| 649 | if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) | 650 | if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) |
| 650 | mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store; | 651 | mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store; |
| 652 | else | ||
| 653 | mk->mp->attrs[mk->mp->num].mattr.store = NULL; | ||
| 651 | mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name; | 654 | mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name; |
| 652 | mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm; | 655 | mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm; |
| 653 | mk->mp->num++; | 656 | mk->mp->num++; |
