diff options
-rw-r--r-- | arch/x86/syscalls/syscall_32.tbl | 1 | ||||
-rw-r--r-- | arch/x86/syscalls/syscall_64.tbl | 1 | ||||
-rw-r--r-- | include/linux/syscalls.h | 1 | ||||
-rw-r--r-- | kernel/module.c | 367 | ||||
-rw-r--r-- | kernel/sys_ni.c | 1 |
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 @@ | |||
356 | 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv | 356 | 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv |
357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev | 357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev |
358 | 349 i386 kcmp sys_kcmp | 358 | 349 i386 kcmp sys_kcmp |
359 | 350 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 @@ | |||
319 | 310 64 process_vm_readv sys_process_vm_readv | 319 | 310 64 process_vm_readv sys_process_vm_readv |
320 | 311 64 process_vm_writev sys_process_vm_writev | 320 | 311 64 process_vm_writev sys_process_vm_writev |
321 | 312 common kcmp sys_kcmp | 321 | 312 common kcmp sys_kcmp |
322 | 313 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 | ||
869 | asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, | 869 | asmlinkage 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); |
871 | asmlinkage 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 |
2428 | static int module_sig_check(struct load_info *info, | 2429 | static 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 */ |
2457 | static int module_sig_check(struct load_info *info, | 2457 | static 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. */ |
2465 | static int copy_and_check(struct load_info *info, | 2464 | static 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. */ | ||
2484 | static 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. */ | ||
2505 | static 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 | ||
2508 | free_hdr: | 2546 | out: |
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. */ | ||
2987 | static 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 */ | ||
2998 | static 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 | |||
3071 | static 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. */ |
2950 | static struct module *load_module(void __user *umod, | 3081 | static 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. */ | ||
3099 | static 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 */ | ||
3110 | SYSCALL_DEFINE3(init_module, void __user *, umod, | 3227 | SYSCALL_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); | 3247 | SYSCALL_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 | ||
3194 | static inline int within(unsigned long addr, void *start, unsigned long size) | 3265 | static 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); | |||
25 | cond_syscall(sys_kexec_load); | 25 | cond_syscall(sys_kexec_load); |
26 | cond_syscall(compat_sys_kexec_load); | 26 | cond_syscall(compat_sys_kexec_load); |
27 | cond_syscall(sys_init_module); | 27 | cond_syscall(sys_init_module); |
28 | cond_syscall(sys_finit_module); | ||
28 | cond_syscall(sys_delete_module); | 29 | cond_syscall(sys_delete_module); |
29 | cond_syscall(sys_socketpair); | 30 | cond_syscall(sys_socketpair); |
30 | cond_syscall(sys_bind); | 31 | cond_syscall(sys_bind); |