aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/kernel/module.c b/kernel/module.c
index d8f8ab271c2b..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
2484static 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. */
2483static int copy_module_from_user(const void __user *umod, unsigned long len, 2500static 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 }
@@ -3352,9 +3369,6 @@ static int load_module(struct load_info *info, const char __user *uargs,
3352 module_bug_cleanup(mod); 3369 module_bug_cleanup(mod);
3353 mutex_unlock(&module_mutex); 3370 mutex_unlock(&module_mutex);
3354 3371
3355 /* Free lock-classes: */
3356 lockdep_free_key_range(mod->module_core, mod->core_size);
3357
3358 /* we can't deallocate the module until we clear memory protection */ 3372 /* we can't deallocate the module until we clear memory protection */
3359 unset_module_init_ro_nx(mod); 3373 unset_module_init_ro_nx(mod);
3360 unset_module_core_ro_nx(mod); 3374 unset_module_core_ro_nx(mod);
@@ -3378,6 +3392,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
3378 synchronize_rcu(); 3392 synchronize_rcu();
3379 mutex_unlock(&module_mutex); 3393 mutex_unlock(&module_mutex);
3380 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
3381 module_deallocate(mod, info); 3398 module_deallocate(mod, info);
3382 free_copy: 3399 free_copy:
3383 free_copy(info); 3400 free_copy(info);