diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/kernel/module.c b/kernel/module.c index b34813f725e9..42a1d2afb217 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #include <linux/async.h> | 56 | #include <linux/async.h> |
57 | #include <linux/percpu.h> | 57 | #include <linux/percpu.h> |
58 | #include <linux/kmemleak.h> | 58 | #include <linux/kmemleak.h> |
59 | #include <linux/kasan.h> | ||
60 | #include <linux/jump_label.h> | 59 | #include <linux/jump_label.h> |
61 | #include <linux/pfn.h> | 60 | #include <linux/pfn.h> |
62 | #include <linux/bsearch.h> | 61 | #include <linux/bsearch.h> |
@@ -388,9 +387,9 @@ static bool check_symbol(const struct symsearch *syms, | |||
388 | pr_warn("Symbol %s is marked as UNUSED, however this module is " | 387 | pr_warn("Symbol %s is marked as UNUSED, however this module is " |
389 | "using it.\n", fsa->name); | 388 | "using it.\n", fsa->name); |
390 | pr_warn("This symbol will go away in the future.\n"); | 389 | pr_warn("This symbol will go away in the future.\n"); |
391 | pr_warn("Please evalute if this is the right api to use and if " | 390 | pr_warn("Please evaluate if this is the right api to use and " |
392 | "it really is, submit a report the linux kernel " | 391 | "if it really is, submit a report to the linux kernel " |
393 | "mailinglist together with submitting your code for " | 392 | "mailing list together with submitting your code for " |
394 | "inclusion.\n"); | 393 | "inclusion.\n"); |
395 | } | 394 | } |
396 | #endif | 395 | #endif |
@@ -1814,7 +1813,6 @@ static void unset_module_init_ro_nx(struct module *mod) { } | |||
1814 | void __weak module_memfree(void *module_region) | 1813 | void __weak module_memfree(void *module_region) |
1815 | { | 1814 | { |
1816 | vfree(module_region); | 1815 | vfree(module_region); |
1817 | kasan_module_free(module_region); | ||
1818 | } | 1816 | } |
1819 | 1817 | ||
1820 | void __weak module_arch_cleanup(struct module *mod) | 1818 | void __weak module_arch_cleanup(struct module *mod) |
@@ -1867,7 +1865,7 @@ static void free_module(struct module *mod) | |||
1867 | kfree(mod->args); | 1865 | kfree(mod->args); |
1868 | percpu_modfree(mod); | 1866 | percpu_modfree(mod); |
1869 | 1867 | ||
1870 | /* Free lock-classes: */ | 1868 | /* Free lock-classes; relies on the preceding sync_rcu(). */ |
1871 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1869 | lockdep_free_key_range(mod->module_core, mod->core_size); |
1872 | 1870 | ||
1873 | /* Finally, free the core (containing the module structure) */ | 1871 | /* Finally, free the core (containing the module structure) */ |
@@ -2313,11 +2311,13 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
2313 | info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); | 2311 | info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); |
2314 | info->stroffs = mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym); | 2312 | info->stroffs = mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym); |
2315 | mod->core_size += strtab_size; | 2313 | mod->core_size += strtab_size; |
2314 | mod->core_size = debug_align(mod->core_size); | ||
2316 | 2315 | ||
2317 | /* Put string table section at end of init part of module. */ | 2316 | /* Put string table section at end of init part of module. */ |
2318 | strsect->sh_flags |= SHF_ALLOC; | 2317 | strsect->sh_flags |= SHF_ALLOC; |
2319 | strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect, | 2318 | strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect, |
2320 | info->index.str) | INIT_OFFSET_MASK; | 2319 | info->index.str) | INIT_OFFSET_MASK; |
2320 | mod->init_size = debug_align(mod->init_size); | ||
2321 | pr_debug("\t%s\n", info->secstrings + strsect->sh_name); | 2321 | pr_debug("\t%s\n", info->secstrings + strsect->sh_name); |
2322 | } | 2322 | } |
2323 | 2323 | ||
@@ -2479,6 +2479,23 @@ static int elf_header_check(struct load_info *info) | |||
2479 | return 0; | 2479 | return 0; |
2480 | } | 2480 | } |
2481 | 2481 | ||
2482 | #define COPY_CHUNK_SIZE (16*PAGE_SIZE) | ||
2483 | |||
2484 | static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned long len) | ||
2485 | { | ||
2486 | do { | ||
2487 | unsigned long n = min(len, COPY_CHUNK_SIZE); | ||
2488 | |||
2489 | if (copy_from_user(dst, usrc, n) != 0) | ||
2490 | return -EFAULT; | ||
2491 | cond_resched(); | ||
2492 | dst += n; | ||
2493 | usrc += n; | ||
2494 | len -= n; | ||
2495 | } while (len); | ||
2496 | return 0; | ||
2497 | } | ||
2498 | |||
2482 | /* Sets info->hdr and info->len. */ | 2499 | /* Sets info->hdr and info->len. */ |
2483 | static int copy_module_from_user(const void __user *umod, unsigned long len, | 2500 | static int copy_module_from_user(const void __user *umod, unsigned long len, |
2484 | struct load_info *info) | 2501 | struct load_info *info) |
@@ -2494,11 +2511,12 @@ static int copy_module_from_user(const void __user *umod, unsigned long len, | |||
2494 | return err; | 2511 | return err; |
2495 | 2512 | ||
2496 | /* Suck in entire file: we'll want most of it. */ | 2513 | /* Suck in entire file: we'll want most of it. */ |
2497 | info->hdr = vmalloc(info->len); | 2514 | info->hdr = __vmalloc(info->len, |
2515 | GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, PAGE_KERNEL); | ||
2498 | if (!info->hdr) | 2516 | if (!info->hdr) |
2499 | return -ENOMEM; | 2517 | return -ENOMEM; |
2500 | 2518 | ||
2501 | if (copy_from_user(info->hdr, umod, info->len) != 0) { | 2519 | if (copy_chunked_from_user(info->hdr, umod, info->len) != 0) { |
2502 | vfree(info->hdr); | 2520 | vfree(info->hdr); |
2503 | return -EFAULT; | 2521 | return -EFAULT; |
2504 | } | 2522 | } |
@@ -2753,6 +2771,9 @@ static int find_module_sections(struct module *mod, struct load_info *info) | |||
2753 | mod->trace_events = section_objs(info, "_ftrace_events", | 2771 | mod->trace_events = section_objs(info, "_ftrace_events", |
2754 | sizeof(*mod->trace_events), | 2772 | sizeof(*mod->trace_events), |
2755 | &mod->num_trace_events); | 2773 | &mod->num_trace_events); |
2774 | mod->trace_enums = section_objs(info, "_ftrace_enum_map", | ||
2775 | sizeof(*mod->trace_enums), | ||
2776 | &mod->num_trace_enums); | ||
2756 | #endif | 2777 | #endif |
2757 | #ifdef CONFIG_TRACING | 2778 | #ifdef CONFIG_TRACING |
2758 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", | 2779 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", |
@@ -3349,9 +3370,6 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3349 | module_bug_cleanup(mod); | 3370 | module_bug_cleanup(mod); |
3350 | mutex_unlock(&module_mutex); | 3371 | mutex_unlock(&module_mutex); |
3351 | 3372 | ||
3352 | /* Free lock-classes: */ | ||
3353 | lockdep_free_key_range(mod->module_core, mod->core_size); | ||
3354 | |||
3355 | /* we can't deallocate the module until we clear memory protection */ | 3373 | /* we can't deallocate the module until we clear memory protection */ |
3356 | unset_module_init_ro_nx(mod); | 3374 | unset_module_init_ro_nx(mod); |
3357 | unset_module_core_ro_nx(mod); | 3375 | unset_module_core_ro_nx(mod); |
@@ -3375,6 +3393,9 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3375 | synchronize_rcu(); | 3393 | synchronize_rcu(); |
3376 | mutex_unlock(&module_mutex); | 3394 | mutex_unlock(&module_mutex); |
3377 | free_module: | 3395 | free_module: |
3396 | /* Free lock-classes; relies on the preceding sync_rcu() */ | ||
3397 | lockdep_free_key_range(mod->module_core, mod->core_size); | ||
3398 | |||
3378 | module_deallocate(mod, info); | 3399 | module_deallocate(mod, info); |
3379 | free_copy: | 3400 | free_copy: |
3380 | free_copy(info); | 3401 | free_copy(info); |