aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2012-10-15 17:01:07 -0400
committerRusty Russell <rusty@rustcorp.com.au>2012-12-13 21:35:22 -0500
commit34e1169d996ab148490c01b65b4ee371cf8ffba2 (patch)
tree3380af46682ce4396c1524bdba8badcab8a51046
parent84ecfd15f5547c992c901df6ec14b4d507eb2c6e (diff)
module: add syscall to load module from fd
As part of the effort to create a stronger boundary between root and kernel, Chrome OS wants to be able to enforce that kernel modules are being loaded only from our read-only crypto-hash verified (dm_verity) root filesystem. Since the init_module syscall hands the kernel a module as a memory blob, no reasoning about the origin of the blob can be made. Earlier proposals for appending signatures to kernel modules would not be useful in Chrome OS, since it would involve adding an additional set of keys to our kernel and builds for no good reason: we already trust the contents of our root filesystem. We don't need to verify those kernel modules a second time. Having to do signature checking on module loading would slow us down and be redundant. All we need to know is where a module is coming from so we can say yes/no to loading it. If a file descriptor is used as the source of a kernel module, many more things can be reasoned about. In Chrome OS's case, we could enforce that the module lives on the filesystem we expect it to live on. In the case of IMA (or other LSMs), it would be possible, for example, to examine extended attributes that may contain signatures over the contents of the module. This introduces a new syscall (on x86), similar to init_module, that has only two arguments. The first argument is used as a file descriptor to the module and the second argument is a pointer to the NULL terminated string of module arguments. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (merge fixes)
-rw-r--r--arch/x86/syscalls/syscall_32.tbl1
-rw-r--r--arch/x86/syscalls/syscall_64.tbl1
-rw-r--r--include/linux/syscalls.h1
-rw-r--r--kernel/module.c367
-rw-r--r--kernel/sys_ni.c1
5 files changed, 223 insertions, 148 deletions
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index a47103fbc692..83b3838417ed 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -356,3 +356,4 @@
356347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv 356347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
357348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev 357348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
358349 i386 kcmp sys_kcmp 358349 i386 kcmp sys_kcmp
359350 i386 finit_module sys_finit_module
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index a582bfed95bb..7c58c84b7bc8 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -319,6 +319,7 @@
319310 64 process_vm_readv sys_process_vm_readv 319310 64 process_vm_readv sys_process_vm_readv
320311 64 process_vm_writev sys_process_vm_writev 320311 64 process_vm_writev sys_process_vm_writev
321312 common kcmp sys_kcmp 321312 common kcmp sys_kcmp
322313 common finit_module sys_finit_module
322 323
323# 324#
324# x32-specific system call numbers start at 512 to avoid cache impact 325# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 727f0cd73921..32bc035bcd68 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -868,4 +868,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
868 868
869asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, 869asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
870 unsigned long idx1, unsigned long idx2); 870 unsigned long idx1, unsigned long idx2);
871asmlinkage long sys_finit_module(int fd, const char __user *uargs);
871#endif 872#endif
diff --git a/kernel/module.c b/kernel/module.c
index 6e48c3a43599..6d2c4e4ca1f5 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -21,6 +21,7 @@
21#include <linux/ftrace_event.h> 21#include <linux/ftrace_event.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/kallsyms.h> 23#include <linux/kallsyms.h>
24#include <linux/file.h>
24#include <linux/fs.h> 25#include <linux/fs.h>
25#include <linux/sysfs.h> 26#include <linux/sysfs.h>
26#include <linux/kernel.h> 27#include <linux/kernel.h>
@@ -2425,18 +2426,17 @@ static inline void kmemleak_load_module(const struct module *mod,
2425#endif 2426#endif
2426 2427
2427#ifdef CONFIG_MODULE_SIG 2428#ifdef CONFIG_MODULE_SIG
2428static int module_sig_check(struct load_info *info, 2429static int module_sig_check(struct load_info *info)
2429 const void *mod, unsigned long *_len)
2430{ 2430{
2431 int err = -ENOKEY; 2431 int err = -ENOKEY;
2432 unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; 2432 const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
2433 unsigned long len = *_len; 2433 const void *mod = info->hdr;
2434 2434
2435 if (len > markerlen && 2435 if (info->len > markerlen &&
2436 memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { 2436 memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
2437 /* We truncate the module to discard the signature */ 2437 /* We truncate the module to discard the signature */
2438 *_len -= markerlen; 2438 info->len -= markerlen;
2439 err = mod_verify_sig(mod, _len); 2439 err = mod_verify_sig(mod, &info->len);
2440 } 2440 }
2441 2441
2442 if (!err) { 2442 if (!err) {
@@ -2454,59 +2454,97 @@ static int module_sig_check(struct load_info *info,
2454 return err; 2454 return err;
2455} 2455}
2456#else /* !CONFIG_MODULE_SIG */ 2456#else /* !CONFIG_MODULE_SIG */
2457static int module_sig_check(struct load_info *info, 2457static int module_sig_check(struct load_info *info)
2458 void *mod, unsigned long *len)
2459{ 2458{
2460 return 0; 2459 return 0;
2461} 2460}
2462#endif /* !CONFIG_MODULE_SIG */ 2461#endif /* !CONFIG_MODULE_SIG */
2463 2462
2464/* Sets info->hdr, info->len and info->sig_ok. */ 2463/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
2465static int copy_and_check(struct load_info *info, 2464static int elf_header_check(struct load_info *info)
2466 const void __user *umod, unsigned long len,
2467 const char __user *uargs)
2468{ 2465{
2469 int err; 2466 if (info->len < sizeof(*(info->hdr)))
2470 Elf_Ehdr *hdr; 2467 return -ENOEXEC;
2468
2469 if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
2470 || info->hdr->e_type != ET_REL
2471 || !elf_check_arch(info->hdr)
2472 || info->hdr->e_shentsize != sizeof(Elf_Shdr))
2473 return -ENOEXEC;
2474
2475 if (info->hdr->e_shoff >= info->len
2476 || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
2477 info->len - info->hdr->e_shoff))
2478 return -ENOEXEC;
2471 2479
2472 if (len < sizeof(*hdr)) 2480 return 0;
2481}
2482
2483/* Sets info->hdr and info->len. */
2484static int copy_module_from_user(const void __user *umod, unsigned long len,
2485 struct load_info *info)
2486{
2487 info->len = len;
2488 if (info->len < sizeof(*(info->hdr)))
2473 return -ENOEXEC; 2489 return -ENOEXEC;
2474 2490
2475 /* Suck in entire file: we'll want most of it. */ 2491 /* Suck in entire file: we'll want most of it. */
2476 if ((hdr = vmalloc(len)) == NULL) 2492 info->hdr = vmalloc(info->len);
2493 if (!info->hdr)
2477 return -ENOMEM; 2494 return -ENOMEM;
2478 2495
2479 if (copy_from_user(hdr, umod, len) != 0) { 2496 if (copy_from_user(info->hdr, umod, info->len) != 0) {
2480 err = -EFAULT; 2497 vfree(info->hdr);
2481 goto free_hdr; 2498 return -EFAULT;
2482 } 2499 }
2483 2500
2484 err = module_sig_check(info, hdr, &len); 2501 return 0;
2502}
2503
2504/* Sets info->hdr and info->len. */
2505static int copy_module_from_fd(int fd, struct load_info *info)
2506{
2507 struct file *file;
2508 int err;
2509 struct kstat stat;
2510 loff_t pos;
2511 ssize_t bytes = 0;
2512
2513 file = fget(fd);
2514 if (!file)
2515 return -ENOEXEC;
2516
2517 err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
2485 if (err) 2518 if (err)
2486 goto free_hdr; 2519 goto out;
2487 2520
2488 /* Sanity checks against insmoding binaries or wrong arch, 2521 if (stat.size > INT_MAX) {
2489 weird elf version */ 2522 err = -EFBIG;
2490 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 2523 goto out;
2491 || hdr->e_type != ET_REL
2492 || !elf_check_arch(hdr)
2493 || hdr->e_shentsize != sizeof(Elf_Shdr)) {
2494 err = -ENOEXEC;
2495 goto free_hdr;
2496 } 2524 }
2497 2525 info->hdr = vmalloc(stat.size);
2498 if (hdr->e_shoff >= len || 2526 if (!info->hdr) {
2499 hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) { 2527 err = -ENOMEM;
2500 err = -ENOEXEC; 2528 goto out;
2501 goto free_hdr;
2502 } 2529 }
2503 2530
2504 info->hdr = hdr; 2531 pos = 0;
2505 info->len = len; 2532 while (pos < stat.size) {
2506 return 0; 2533 bytes = kernel_read(file, pos, (char *)(info->hdr) + pos,
2534 stat.size - pos);
2535 if (bytes < 0) {
2536 vfree(info->hdr);
2537 err = bytes;
2538 goto out;
2539 }
2540 if (bytes == 0)
2541 break;
2542 pos += bytes;
2543 }
2544 info->len = pos;
2507 2545
2508free_hdr: 2546out:
2509 vfree(hdr); 2547 fput(file);
2510 return err; 2548 return err;
2511} 2549}
2512 2550
@@ -2945,33 +2983,123 @@ static bool finished_loading(const char *name)
2945 return ret; 2983 return ret;
2946} 2984}
2947 2985
2986/* Call module constructors. */
2987static void do_mod_ctors(struct module *mod)
2988{
2989#ifdef CONFIG_CONSTRUCTORS
2990 unsigned long i;
2991
2992 for (i = 0; i < mod->num_ctors; i++)
2993 mod->ctors[i]();
2994#endif
2995}
2996
2997/* This is where the real work happens */
2998static int do_init_module(struct module *mod)
2999{
3000 int ret = 0;
3001
3002 blocking_notifier_call_chain(&module_notify_list,
3003 MODULE_STATE_COMING, mod);
3004
3005 /* Set RO and NX regions for core */
3006 set_section_ro_nx(mod->module_core,
3007 mod->core_text_size,
3008 mod->core_ro_size,
3009 mod->core_size);
3010
3011 /* Set RO and NX regions for init */
3012 set_section_ro_nx(mod->module_init,
3013 mod->init_text_size,
3014 mod->init_ro_size,
3015 mod->init_size);
3016
3017 do_mod_ctors(mod);
3018 /* Start the module */
3019 if (mod->init != NULL)
3020 ret = do_one_initcall(mod->init);
3021 if (ret < 0) {
3022 /* Init routine failed: abort. Try to protect us from
3023 buggy refcounters. */
3024 mod->state = MODULE_STATE_GOING;
3025 synchronize_sched();
3026 module_put(mod);
3027 blocking_notifier_call_chain(&module_notify_list,
3028 MODULE_STATE_GOING, mod);
3029 free_module(mod);
3030 wake_up_all(&module_wq);
3031 return ret;
3032 }
3033 if (ret > 0) {
3034 printk(KERN_WARNING
3035"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
3036"%s: loading module anyway...\n",
3037 __func__, mod->name, ret,
3038 __func__);
3039 dump_stack();
3040 }
3041
3042 /* Now it's a first class citizen! */
3043 mod->state = MODULE_STATE_LIVE;
3044 blocking_notifier_call_chain(&module_notify_list,
3045 MODULE_STATE_LIVE, mod);
3046
3047 /* We need to finish all async code before the module init sequence is done */
3048 async_synchronize_full();
3049
3050 mutex_lock(&module_mutex);
3051 /* Drop initial reference. */
3052 module_put(mod);
3053 trim_init_extable(mod);
3054#ifdef CONFIG_KALLSYMS
3055 mod->num_symtab = mod->core_num_syms;
3056 mod->symtab = mod->core_symtab;
3057 mod->strtab = mod->core_strtab;
3058#endif
3059 unset_module_init_ro_nx(mod);
3060 module_free(mod, mod->module_init);
3061 mod->module_init = NULL;
3062 mod->init_size = 0;
3063 mod->init_ro_size = 0;
3064 mod->init_text_size = 0;
3065 mutex_unlock(&module_mutex);
3066 wake_up_all(&module_wq);
3067
3068 return 0;
3069}
3070
3071static int may_init_module(void)
3072{
3073 if (!capable(CAP_SYS_MODULE) || modules_disabled)
3074 return -EPERM;
3075
3076 return 0;
3077}
3078
2948/* Allocate and load the module: note that size of section 0 is always 3079/* Allocate and load the module: note that size of section 0 is always
2949 zero, and we rely on this for optional sections. */ 3080 zero, and we rely on this for optional sections. */
2950static struct module *load_module(void __user *umod, 3081static int load_module(struct load_info *info, const char __user *uargs)
2951 unsigned long len,
2952 const char __user *uargs)
2953{ 3082{
2954 struct load_info info = { NULL, };
2955 struct module *mod, *old; 3083 struct module *mod, *old;
2956 long err; 3084 long err;
2957 3085
2958 pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", 3086 err = module_sig_check(info);
2959 umod, len, uargs); 3087 if (err)
3088 goto free_copy;
2960 3089
2961 /* Copy in the blobs from userspace, check they are vaguely sane. */ 3090 err = elf_header_check(info);
2962 err = copy_and_check(&info, umod, len, uargs);
2963 if (err) 3091 if (err)
2964 return ERR_PTR(err); 3092 goto free_copy;
2965 3093
2966 /* Figure out module layout, and allocate all the memory. */ 3094 /* Figure out module layout, and allocate all the memory. */
2967 mod = layout_and_allocate(&info); 3095 mod = layout_and_allocate(info);
2968 if (IS_ERR(mod)) { 3096 if (IS_ERR(mod)) {
2969 err = PTR_ERR(mod); 3097 err = PTR_ERR(mod);
2970 goto free_copy; 3098 goto free_copy;
2971 } 3099 }
2972 3100
2973#ifdef CONFIG_MODULE_SIG 3101#ifdef CONFIG_MODULE_SIG
2974 mod->sig_ok = info.sig_ok; 3102 mod->sig_ok = info->sig_ok;
2975 if (!mod->sig_ok) 3103 if (!mod->sig_ok)
2976 add_taint_module(mod, TAINT_FORCED_MODULE); 3104 add_taint_module(mod, TAINT_FORCED_MODULE);
2977#endif 3105#endif
@@ -2983,25 +3111,25 @@ static struct module *load_module(void __user *umod,
2983 3111
2984 /* Now we've got everything in the final locations, we can 3112 /* Now we've got everything in the final locations, we can
2985 * find optional sections. */ 3113 * find optional sections. */
2986 find_module_sections(mod, &info); 3114 find_module_sections(mod, info);
2987 3115
2988 err = check_module_license_and_versions(mod); 3116 err = check_module_license_and_versions(mod);
2989 if (err) 3117 if (err)
2990 goto free_unload; 3118 goto free_unload;
2991 3119
2992 /* Set up MODINFO_ATTR fields */ 3120 /* Set up MODINFO_ATTR fields */
2993 setup_modinfo(mod, &info); 3121 setup_modinfo(mod, info);
2994 3122
2995 /* Fix up syms, so that st_value is a pointer to location. */ 3123 /* Fix up syms, so that st_value is a pointer to location. */
2996 err = simplify_symbols(mod, &info); 3124 err = simplify_symbols(mod, info);
2997 if (err < 0) 3125 if (err < 0)
2998 goto free_modinfo; 3126 goto free_modinfo;
2999 3127
3000 err = apply_relocations(mod, &info); 3128 err = apply_relocations(mod, info);
3001 if (err < 0) 3129 if (err < 0)
3002 goto free_modinfo; 3130 goto free_modinfo;
3003 3131
3004 err = post_relocation(mod, &info); 3132 err = post_relocation(mod, info);
3005 if (err < 0) 3133 if (err < 0)
3006 goto free_modinfo; 3134 goto free_modinfo;
3007 3135
@@ -3041,14 +3169,14 @@ again:
3041 } 3169 }
3042 3170
3043 /* This has to be done once we're sure module name is unique. */ 3171 /* This has to be done once we're sure module name is unique. */
3044 dynamic_debug_setup(info.debug, info.num_debug); 3172 dynamic_debug_setup(info->debug, info->num_debug);
3045 3173
3046 /* Find duplicate symbols */ 3174 /* Find duplicate symbols */
3047 err = verify_export_symbols(mod); 3175 err = verify_export_symbols(mod);
3048 if (err < 0) 3176 if (err < 0)
3049 goto ddebug; 3177 goto ddebug;
3050 3178
3051 module_bug_finalize(info.hdr, info.sechdrs, mod); 3179 module_bug_finalize(info->hdr, info->sechdrs, mod);
3052 list_add_rcu(&mod->list, &modules); 3180 list_add_rcu(&mod->list, &modules);
3053 mutex_unlock(&module_mutex); 3181 mutex_unlock(&module_mutex);
3054 3182
@@ -3059,16 +3187,17 @@ again:
3059 goto unlink; 3187 goto unlink;
3060 3188
3061 /* Link in to syfs. */ 3189 /* Link in to syfs. */
3062 err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp); 3190 err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
3063 if (err < 0) 3191 if (err < 0)
3064 goto unlink; 3192 goto unlink;
3065 3193
3066 /* Get rid of temporary copy. */ 3194 /* Get rid of temporary copy. */
3067 free_copy(&info); 3195 free_copy(info);
3068 3196
3069 /* Done! */ 3197 /* Done! */
3070 trace_module_load(mod); 3198 trace_module_load(mod);
3071 return mod; 3199
3200 return do_init_module(mod);
3072 3201
3073 unlink: 3202 unlink:
3074 mutex_lock(&module_mutex); 3203 mutex_lock(&module_mutex);
@@ -3077,7 +3206,7 @@ again:
3077 module_bug_cleanup(mod); 3206 module_bug_cleanup(mod);
3078 wake_up_all(&module_wq); 3207 wake_up_all(&module_wq);
3079 ddebug: 3208 ddebug:
3080 dynamic_debug_remove(info.debug); 3209 dynamic_debug_remove(info->debug);
3081 unlock: 3210 unlock:
3082 mutex_unlock(&module_mutex); 3211 mutex_unlock(&module_mutex);
3083 synchronize_sched(); 3212 synchronize_sched();
@@ -3089,106 +3218,48 @@ again:
3089 free_unload: 3218 free_unload:
3090 module_unload_free(mod); 3219 module_unload_free(mod);
3091 free_module: 3220 free_module:
3092 module_deallocate(mod, &info); 3221 module_deallocate(mod, info);
3093 free_copy: 3222 free_copy:
3094 free_copy(&info); 3223 free_copy(info);
3095 return ERR_PTR(err); 3224 return err;
3096}
3097
3098/* Call module constructors. */
3099static void do_mod_ctors(struct module *mod)
3100{
3101#ifdef CONFIG_CONSTRUCTORS
3102 unsigned long i;
3103
3104 for (i = 0; i < mod->num_ctors; i++)
3105 mod->ctors[i]();
3106#endif
3107} 3225}
3108 3226
3109/* This is where the real work happens */
3110SYSCALL_DEFINE3(init_module, void __user *, umod, 3227SYSCALL_DEFINE3(init_module, void __user *, umod,
3111 unsigned long, len, const char __user *, uargs) 3228 unsigned long, len, const char __user *, uargs)
3112{ 3229{
3113 struct module *mod; 3230 int err;
3114 int ret = 0; 3231 struct load_info info = { };
3115
3116 /* Must have permission */
3117 if (!capable(CAP_SYS_MODULE) || modules_disabled)
3118 return -EPERM;
3119 3232
3120 /* Do all the hard work */ 3233 err = may_init_module();
3121 mod = load_module(umod, len, uargs); 3234 if (err)
3122 if (IS_ERR(mod)) 3235 return err;
3123 return PTR_ERR(mod);
3124 3236
3125 blocking_notifier_call_chain(&module_notify_list, 3237 pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
3126 MODULE_STATE_COMING, mod); 3238 umod, len, uargs);
3127 3239
3128 /* Set RO and NX regions for core */ 3240 err = copy_module_from_user(umod, len, &info);
3129 set_section_ro_nx(mod->module_core, 3241 if (err)
3130 mod->core_text_size, 3242 return err;
3131 mod->core_ro_size,
3132 mod->core_size);
3133 3243
3134 /* Set RO and NX regions for init */ 3244 return load_module(&info, uargs);
3135 set_section_ro_nx(mod->module_init, 3245}
3136 mod->init_text_size,
3137 mod->init_ro_size,
3138 mod->init_size);
3139 3246
3140 do_mod_ctors(mod); 3247SYSCALL_DEFINE2(finit_module, int, fd, const char __user *, uargs)
3141 /* Start the module */ 3248{
3142 if (mod->init != NULL) 3249 int err;
3143 ret = do_one_initcall(mod->init); 3250 struct load_info info = { };
3144 if (ret < 0) {
3145 /* Init routine failed: abort. Try to protect us from
3146 buggy refcounters. */
3147 mod->state = MODULE_STATE_GOING;
3148 synchronize_sched();
3149 module_put(mod);
3150 blocking_notifier_call_chain(&module_notify_list,
3151 MODULE_STATE_GOING, mod);
3152 free_module(mod);
3153 wake_up_all(&module_wq);
3154 return ret;
3155 }
3156 if (ret > 0) {
3157 printk(KERN_WARNING
3158"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
3159"%s: loading module anyway...\n",
3160 __func__, mod->name, ret,
3161 __func__);
3162 dump_stack();
3163 }
3164 3251
3165 /* Now it's a first class citizen! */ 3252 err = may_init_module();
3166 mod->state = MODULE_STATE_LIVE; 3253 if (err)
3167 blocking_notifier_call_chain(&module_notify_list, 3254 return err;
3168 MODULE_STATE_LIVE, mod);
3169 3255
3170 /* We need to finish all async code before the module init sequence is done */ 3256 pr_debug("finit_module: fd=%d, uargs=%p\n", fd, uargs);
3171 async_synchronize_full();
3172 3257
3173 mutex_lock(&module_mutex); 3258 err = copy_module_from_fd(fd, &info);
3174 /* Drop initial reference. */ 3259 if (err)
3175 module_put(mod); 3260 return err;
3176 trim_init_extable(mod);
3177#ifdef CONFIG_KALLSYMS
3178 mod->num_symtab = mod->core_num_syms;
3179 mod->symtab = mod->core_symtab;
3180 mod->strtab = mod->core_strtab;
3181#endif
3182 unset_module_init_ro_nx(mod);
3183 module_free(mod, mod->module_init);
3184 mod->module_init = NULL;
3185 mod->init_size = 0;
3186 mod->init_ro_size = 0;
3187 mod->init_text_size = 0;
3188 mutex_unlock(&module_mutex);
3189 wake_up_all(&module_wq);
3190 3261
3191 return 0; 3262 return load_module(&info, uargs);
3192} 3263}
3193 3264
3194static inline int within(unsigned long addr, void *start, unsigned long size) 3265static inline int within(unsigned long addr, void *start, unsigned long size)
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index dbff751e4086..395084d4ce16 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -25,6 +25,7 @@ cond_syscall(sys_swapoff);
25cond_syscall(sys_kexec_load); 25cond_syscall(sys_kexec_load);
26cond_syscall(compat_sys_kexec_load); 26cond_syscall(compat_sys_kexec_load);
27cond_syscall(sys_init_module); 27cond_syscall(sys_init_module);
28cond_syscall(sys_finit_module);
28cond_syscall(sys_delete_module); 29cond_syscall(sys_delete_module);
29cond_syscall(sys_socketpair); 30cond_syscall(sys_socketpair);
30cond_syscall(sys_bind); 31cond_syscall(sys_bind);