diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/kernel/module.c b/kernel/module.c index 99fdf94efce8..42a1d2afb217 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -387,9 +387,9 @@ static bool check_symbol(const struct symsearch *syms, | |||
387 | 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 " |
388 | "using it.\n", fsa->name); | 388 | "using it.\n", fsa->name); |
389 | pr_warn("This symbol will go away in the future.\n"); | 389 | pr_warn("This symbol will go away in the future.\n"); |
390 | 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 " |
391 | "it really is, submit a report the linux kernel " | 391 | "if it really is, submit a report to the linux kernel " |
392 | "mailinglist together with submitting your code for " | 392 | "mailing list together with submitting your code for " |
393 | "inclusion.\n"); | 393 | "inclusion.\n"); |
394 | } | 394 | } |
395 | #endif | 395 | #endif |
@@ -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", |