diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/kernel/module.c b/kernel/module.c index b3d634ed06c9..650b038ae520 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -1865,7 +1865,7 @@ static void free_module(struct module *mod) | |||
| 1865 | kfree(mod->args); | 1865 | kfree(mod->args); |
| 1866 | percpu_modfree(mod); | 1866 | percpu_modfree(mod); |
| 1867 | 1867 | ||
| 1868 | /* Free lock-classes: */ | 1868 | /* Free lock-classes; relies on the preceding sync_rcu(). */ |
| 1869 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1869 | lockdep_free_key_range(mod->module_core, mod->core_size); |
| 1870 | 1870 | ||
| 1871 | /* Finally, free the core (containing the module structure) */ | 1871 | /* Finally, free the core (containing the module structure) */ |
| @@ -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) |
| @@ -2498,7 +2515,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len, | |||
| 2498 | if (!info->hdr) | 2515 | if (!info->hdr) |
| 2499 | return -ENOMEM; | 2516 | return -ENOMEM; |
| 2500 | 2517 | ||
| 2501 | if (copy_from_user(info->hdr, umod, info->len) != 0) { | 2518 | if (copy_chunked_from_user(info->hdr, umod, info->len) != 0) { |
| 2502 | vfree(info->hdr); | 2519 | vfree(info->hdr); |
| 2503 | return -EFAULT; | 2520 | return -EFAULT; |
| 2504 | } | 2521 | } |
| @@ -2753,6 +2770,9 @@ static int find_module_sections(struct module *mod, struct load_info *info) | |||
| 2753 | mod->trace_events = section_objs(info, "_ftrace_events", | 2770 | mod->trace_events = section_objs(info, "_ftrace_events", |
| 2754 | sizeof(*mod->trace_events), | 2771 | sizeof(*mod->trace_events), |
| 2755 | &mod->num_trace_events); | 2772 | &mod->num_trace_events); |
| 2773 | mod->trace_enums = section_objs(info, "_ftrace_enum_map", | ||
| 2774 | sizeof(*mod->trace_enums), | ||
| 2775 | &mod->num_trace_enums); | ||
| 2756 | #endif | 2776 | #endif |
| 2757 | #ifdef CONFIG_TRACING | 2777 | #ifdef CONFIG_TRACING |
| 2758 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", | 2778 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", |
| @@ -3349,9 +3369,6 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3349 | module_bug_cleanup(mod); | 3369 | module_bug_cleanup(mod); |
| 3350 | mutex_unlock(&module_mutex); | 3370 | mutex_unlock(&module_mutex); |
| 3351 | 3371 | ||
| 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 */ | 3372 | /* we can't deallocate the module until we clear memory protection */ |
| 3356 | unset_module_init_ro_nx(mod); | 3373 | unset_module_init_ro_nx(mod); |
| 3357 | unset_module_core_ro_nx(mod); | 3374 | unset_module_core_ro_nx(mod); |
| @@ -3375,6 +3392,9 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3375 | synchronize_rcu(); | 3392 | synchronize_rcu(); |
| 3376 | mutex_unlock(&module_mutex); | 3393 | mutex_unlock(&module_mutex); |
| 3377 | free_module: | 3394 | free_module: |
| 3395 | /* Free lock-classes; relies on the preceding sync_rcu() */ | ||
| 3396 | lockdep_free_key_range(mod->module_core, mod->core_size); | ||
| 3397 | |||
| 3378 | module_deallocate(mod, info); | 3398 | module_deallocate(mod, info); |
| 3379 | free_copy: | 3399 | free_copy: |
| 3380 | free_copy(info); | 3400 | free_copy(info); |
