diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 39 |
1 files changed, 16 insertions, 23 deletions
diff --git a/kernel/module.c b/kernel/module.c index 0925c9a71975..cab4bce49c23 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1209,10 +1209,11 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
1209 | 1209 | ||
1210 | /* Since this should be found in kernel (which can't be removed), | 1210 | /* Since this should be found in kernel (which can't be removed), |
1211 | * no locking is necessary. */ | 1211 | * no locking is necessary. */ |
1212 | if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, | 1212 | if (!find_symbol(VMLINUX_SYMBOL_STR(module_layout), NULL, |
1213 | &crc, true, false)) | 1213 | &crc, true, false)) |
1214 | BUG(); | 1214 | BUG(); |
1215 | return check_version(sechdrs, versindex, "module_layout", mod, crc, | 1215 | return check_version(sechdrs, versindex, |
1216 | VMLINUX_SYMBOL_STR(module_layout), mod, crc, | ||
1216 | NULL); | 1217 | NULL); |
1217 | } | 1218 | } |
1218 | 1219 | ||
@@ -1861,12 +1862,12 @@ static void free_module(struct module *mod) | |||
1861 | { | 1862 | { |
1862 | trace_module_free(mod); | 1863 | trace_module_free(mod); |
1863 | 1864 | ||
1864 | /* Delete from various lists */ | ||
1865 | mutex_lock(&module_mutex); | ||
1866 | stop_machine(__unlink_module, mod, NULL); | ||
1867 | mutex_unlock(&module_mutex); | ||
1868 | mod_sysfs_teardown(mod); | 1865 | mod_sysfs_teardown(mod); |
1869 | 1866 | ||
1867 | /* We leave it in list to prevent duplicate loads, but make sure | ||
1868 | * that noone uses it while it's being deconstructed. */ | ||
1869 | mod->state = MODULE_STATE_UNFORMED; | ||
1870 | |||
1870 | /* Remove dynamic debug info */ | 1871 | /* Remove dynamic debug info */ |
1871 | ddebug_remove_module(mod->name); | 1872 | ddebug_remove_module(mod->name); |
1872 | 1873 | ||
@@ -1879,6 +1880,11 @@ static void free_module(struct module *mod) | |||
1879 | /* Free any allocated parameters. */ | 1880 | /* Free any allocated parameters. */ |
1880 | destroy_params(mod->kp, mod->num_kp); | 1881 | destroy_params(mod->kp, mod->num_kp); |
1881 | 1882 | ||
1883 | /* Now we can delete it from the lists */ | ||
1884 | mutex_lock(&module_mutex); | ||
1885 | stop_machine(__unlink_module, mod, NULL); | ||
1886 | mutex_unlock(&module_mutex); | ||
1887 | |||
1882 | /* This may be NULL, but that's OK */ | 1888 | /* This may be NULL, but that's OK */ |
1883 | unset_module_init_ro_nx(mod); | 1889 | unset_module_init_ro_nx(mod); |
1884 | module_free(mod, mod->module_init); | 1890 | module_free(mod, mod->module_init); |
@@ -2425,10 +2431,10 @@ static void kmemleak_load_module(const struct module *mod, | |||
2425 | kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); | 2431 | kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); |
2426 | 2432 | ||
2427 | for (i = 1; i < info->hdr->e_shnum; i++) { | 2433 | for (i = 1; i < info->hdr->e_shnum; i++) { |
2428 | const char *name = info->secstrings + info->sechdrs[i].sh_name; | 2434 | /* Scan all writable sections that's not executable */ |
2429 | if (!(info->sechdrs[i].sh_flags & SHF_ALLOC)) | 2435 | if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) || |
2430 | continue; | 2436 | !(info->sechdrs[i].sh_flags & SHF_WRITE) || |
2431 | if (!strstarts(name, ".data") && !strstarts(name, ".bss")) | 2437 | (info->sechdrs[i].sh_flags & SHF_EXECINSTR)) |
2432 | continue; | 2438 | continue; |
2433 | 2439 | ||
2434 | kmemleak_scan_area((void *)info->sechdrs[i].sh_addr, | 2440 | kmemleak_scan_area((void *)info->sechdrs[i].sh_addr, |
@@ -2763,24 +2769,11 @@ static void find_module_sections(struct module *mod, struct load_info *info) | |||
2763 | mod->trace_events = section_objs(info, "_ftrace_events", | 2769 | mod->trace_events = section_objs(info, "_ftrace_events", |
2764 | sizeof(*mod->trace_events), | 2770 | sizeof(*mod->trace_events), |
2765 | &mod->num_trace_events); | 2771 | &mod->num_trace_events); |
2766 | /* | ||
2767 | * This section contains pointers to allocated objects in the trace | ||
2768 | * code and not scanning it leads to false positives. | ||
2769 | */ | ||
2770 | kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) * | ||
2771 | mod->num_trace_events, GFP_KERNEL); | ||
2772 | #endif | 2772 | #endif |
2773 | #ifdef CONFIG_TRACING | 2773 | #ifdef CONFIG_TRACING |
2774 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", | 2774 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", |
2775 | sizeof(*mod->trace_bprintk_fmt_start), | 2775 | sizeof(*mod->trace_bprintk_fmt_start), |
2776 | &mod->num_trace_bprintk_fmt); | 2776 | &mod->num_trace_bprintk_fmt); |
2777 | /* | ||
2778 | * This section contains pointers to allocated objects in the trace | ||
2779 | * code and not scanning it leads to false positives. | ||
2780 | */ | ||
2781 | kmemleak_scan_area(mod->trace_bprintk_fmt_start, | ||
2782 | sizeof(*mod->trace_bprintk_fmt_start) * | ||
2783 | mod->num_trace_bprintk_fmt, GFP_KERNEL); | ||
2784 | #endif | 2777 | #endif |
2785 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD | 2778 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD |
2786 | /* sechdrs[0].sh_size is always zero */ | 2779 | /* sechdrs[0].sh_size is always zero */ |