diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 77 |
1 files changed, 43 insertions, 34 deletions
diff --git a/kernel/module.c b/kernel/module.c index cab4bce49c23..206915830d29 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -455,7 +455,7 @@ const struct kernel_symbol *find_symbol(const char *name, | |||
| 455 | EXPORT_SYMBOL_GPL(find_symbol); | 455 | EXPORT_SYMBOL_GPL(find_symbol); |
| 456 | 456 | ||
| 457 | /* Search for module by name: must hold module_mutex. */ | 457 | /* Search for module by name: must hold module_mutex. */ |
| 458 | static struct module *find_module_all(const char *name, | 458 | static struct module *find_module_all(const char *name, size_t len, |
| 459 | bool even_unformed) | 459 | bool even_unformed) |
| 460 | { | 460 | { |
| 461 | struct module *mod; | 461 | struct module *mod; |
| @@ -463,7 +463,7 @@ static struct module *find_module_all(const char *name, | |||
| 463 | list_for_each_entry(mod, &modules, list) { | 463 | list_for_each_entry(mod, &modules, list) { |
| 464 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) | 464 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) |
| 465 | continue; | 465 | continue; |
| 466 | if (strcmp(mod->name, name) == 0) | 466 | if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) |
| 467 | return mod; | 467 | return mod; |
| 468 | } | 468 | } |
| 469 | return NULL; | 469 | return NULL; |
| @@ -471,7 +471,7 @@ static struct module *find_module_all(const char *name, | |||
| 471 | 471 | ||
| 472 | struct module *find_module(const char *name) | 472 | struct module *find_module(const char *name) |
| 473 | { | 473 | { |
| 474 | return find_module_all(name, false); | 474 | return find_module_all(name, strlen(name), false); |
| 475 | } | 475 | } |
| 476 | EXPORT_SYMBOL_GPL(find_module); | 476 | EXPORT_SYMBOL_GPL(find_module); |
| 477 | 477 | ||
| @@ -482,23 +482,28 @@ static inline void __percpu *mod_percpu(struct module *mod) | |||
| 482 | return mod->percpu; | 482 | return mod->percpu; |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | static int percpu_modalloc(struct module *mod, | 485 | static int percpu_modalloc(struct module *mod, struct load_info *info) |
| 486 | unsigned long size, unsigned long align) | ||
| 487 | { | 486 | { |
| 487 | Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; | ||
| 488 | unsigned long align = pcpusec->sh_addralign; | ||
| 489 | |||
| 490 | if (!pcpusec->sh_size) | ||
| 491 | return 0; | ||
| 492 | |||
| 488 | if (align > PAGE_SIZE) { | 493 | if (align > PAGE_SIZE) { |
| 489 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", | 494 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", |
| 490 | mod->name, align, PAGE_SIZE); | 495 | mod->name, align, PAGE_SIZE); |
| 491 | align = PAGE_SIZE; | 496 | align = PAGE_SIZE; |
| 492 | } | 497 | } |
| 493 | 498 | ||
| 494 | mod->percpu = __alloc_reserved_percpu(size, align); | 499 | mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align); |
| 495 | if (!mod->percpu) { | 500 | if (!mod->percpu) { |
| 496 | printk(KERN_WARNING | 501 | printk(KERN_WARNING |
| 497 | "%s: Could not allocate %lu bytes percpu data\n", | 502 | "%s: Could not allocate %lu bytes percpu data\n", |
| 498 | mod->name, size); | 503 | mod->name, (unsigned long)pcpusec->sh_size); |
| 499 | return -ENOMEM; | 504 | return -ENOMEM; |
| 500 | } | 505 | } |
| 501 | mod->percpu_size = size; | 506 | mod->percpu_size = pcpusec->sh_size; |
| 502 | return 0; | 507 | return 0; |
| 503 | } | 508 | } |
| 504 | 509 | ||
| @@ -563,10 +568,12 @@ static inline void __percpu *mod_percpu(struct module *mod) | |||
| 563 | { | 568 | { |
| 564 | return NULL; | 569 | return NULL; |
| 565 | } | 570 | } |
| 566 | static inline int percpu_modalloc(struct module *mod, | 571 | static int percpu_modalloc(struct module *mod, struct load_info *info) |
| 567 | unsigned long size, unsigned long align) | ||
| 568 | { | 572 | { |
| 569 | return -ENOMEM; | 573 | /* UP modules shouldn't have this section: ENOMEM isn't quite right */ |
| 574 | if (info->sechdrs[info->index.pcpu].sh_size != 0) | ||
| 575 | return -ENOMEM; | ||
| 576 | return 0; | ||
| 570 | } | 577 | } |
| 571 | static inline void percpu_modfree(struct module *mod) | 578 | static inline void percpu_modfree(struct module *mod) |
| 572 | { | 579 | { |
| @@ -2927,7 +2934,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
| 2927 | { | 2934 | { |
| 2928 | /* Module within temporary copy. */ | 2935 | /* Module within temporary copy. */ |
| 2929 | struct module *mod; | 2936 | struct module *mod; |
| 2930 | Elf_Shdr *pcpusec; | ||
| 2931 | int err; | 2937 | int err; |
| 2932 | 2938 | ||
| 2933 | mod = setup_load_info(info, flags); | 2939 | mod = setup_load_info(info, flags); |
| @@ -2942,17 +2948,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
| 2942 | err = module_frob_arch_sections(info->hdr, info->sechdrs, | 2948 | err = module_frob_arch_sections(info->hdr, info->sechdrs, |
| 2943 | info->secstrings, mod); | 2949 | info->secstrings, mod); |
| 2944 | if (err < 0) | 2950 | if (err < 0) |
| 2945 | goto out; | 2951 | return ERR_PTR(err); |
| 2946 | 2952 | ||
| 2947 | pcpusec = &info->sechdrs[info->index.pcpu]; | 2953 | /* We will do a special allocation for per-cpu sections later. */ |
| 2948 | if (pcpusec->sh_size) { | 2954 | info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2949 | /* We have a special allocation for this section. */ | ||
| 2950 | err = percpu_modalloc(mod, | ||
| 2951 | pcpusec->sh_size, pcpusec->sh_addralign); | ||
| 2952 | if (err) | ||
| 2953 | goto out; | ||
| 2954 | pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC; | ||
| 2955 | } | ||
| 2956 | 2955 | ||
| 2957 | /* Determine total sizes, and put offsets in sh_entsize. For now | 2956 | /* Determine total sizes, and put offsets in sh_entsize. For now |
| 2958 | this is done generically; there doesn't appear to be any | 2957 | this is done generically; there doesn't appear to be any |
| @@ -2963,17 +2962,12 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
| 2963 | /* Allocate and move to the final place */ | 2962 | /* Allocate and move to the final place */ |
| 2964 | err = move_module(mod, info); | 2963 | err = move_module(mod, info); |
| 2965 | if (err) | 2964 | if (err) |
| 2966 | goto free_percpu; | 2965 | return ERR_PTR(err); |
| 2967 | 2966 | ||
| 2968 | /* Module has been copied to its final place now: return it. */ | 2967 | /* Module has been copied to its final place now: return it. */ |
| 2969 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; | 2968 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; |
| 2970 | kmemleak_load_module(mod, info); | 2969 | kmemleak_load_module(mod, info); |
| 2971 | return mod; | 2970 | return mod; |
| 2972 | |||
| 2973 | free_percpu: | ||
| 2974 | percpu_modfree(mod); | ||
| 2975 | out: | ||
| 2976 | return ERR_PTR(err); | ||
| 2977 | } | 2971 | } |
| 2978 | 2972 | ||
| 2979 | /* mod is no longer valid after this! */ | 2973 | /* mod is no longer valid after this! */ |
| @@ -3014,7 +3008,7 @@ static bool finished_loading(const char *name) | |||
| 3014 | bool ret; | 3008 | bool ret; |
| 3015 | 3009 | ||
| 3016 | mutex_lock(&module_mutex); | 3010 | mutex_lock(&module_mutex); |
| 3017 | mod = find_module_all(name, true); | 3011 | mod = find_module_all(name, strlen(name), true); |
| 3018 | ret = !mod || mod->state == MODULE_STATE_LIVE | 3012 | ret = !mod || mod->state == MODULE_STATE_LIVE |
| 3019 | || mod->state == MODULE_STATE_GOING; | 3013 | || mod->state == MODULE_STATE_GOING; |
| 3020 | mutex_unlock(&module_mutex); | 3014 | mutex_unlock(&module_mutex); |
| @@ -3152,7 +3146,8 @@ static int add_unformed_module(struct module *mod) | |||
| 3152 | 3146 | ||
| 3153 | again: | 3147 | again: |
| 3154 | mutex_lock(&module_mutex); | 3148 | mutex_lock(&module_mutex); |
| 3155 | if ((old = find_module_all(mod->name, true)) != NULL) { | 3149 | old = find_module_all(mod->name, strlen(mod->name), true); |
| 3150 | if (old != NULL) { | ||
| 3156 | if (old->state == MODULE_STATE_COMING | 3151 | if (old->state == MODULE_STATE_COMING |
| 3157 | || old->state == MODULE_STATE_UNFORMED) { | 3152 | || old->state == MODULE_STATE_UNFORMED) { |
| 3158 | /* Wait in case it fails to load. */ | 3153 | /* Wait in case it fails to load. */ |
| @@ -3198,6 +3193,17 @@ out: | |||
| 3198 | return err; | 3193 | return err; |
| 3199 | } | 3194 | } |
| 3200 | 3195 | ||
| 3196 | static int unknown_module_param_cb(char *param, char *val, const char *modname) | ||
| 3197 | { | ||
| 3198 | /* Check for magic 'dyndbg' arg */ | ||
| 3199 | int ret = ddebug_dyndbg_module_param_cb(param, val, modname); | ||
| 3200 | if (ret != 0) { | ||
| 3201 | printk(KERN_WARNING "%s: unknown parameter '%s' ignored\n", | ||
| 3202 | modname, param); | ||
| 3203 | } | ||
| 3204 | return 0; | ||
| 3205 | } | ||
| 3206 | |||
| 3201 | /* Allocate and load the module: note that size of section 0 is always | 3207 | /* Allocate and load the module: note that size of section 0 is always |
| 3202 | zero, and we rely on this for optional sections. */ | 3208 | zero, and we rely on this for optional sections. */ |
| 3203 | static int load_module(struct load_info *info, const char __user *uargs, | 3209 | static int load_module(struct load_info *info, const char __user *uargs, |
| @@ -3237,6 +3243,11 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3237 | } | 3243 | } |
| 3238 | #endif | 3244 | #endif |
| 3239 | 3245 | ||
| 3246 | /* To avoid stressing percpu allocator, do this once we're unique. */ | ||
| 3247 | err = percpu_modalloc(mod, info); | ||
| 3248 | if (err) | ||
| 3249 | goto unlink_mod; | ||
| 3250 | |||
| 3240 | /* Now module is in final location, initialize linked lists, etc. */ | 3251 | /* Now module is in final location, initialize linked lists, etc. */ |
| 3241 | err = module_unload_init(mod); | 3252 | err = module_unload_init(mod); |
| 3242 | if (err) | 3253 | if (err) |
| @@ -3284,7 +3295,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3284 | 3295 | ||
| 3285 | /* Module is ready to execute: parsing args may do that. */ | 3296 | /* Module is ready to execute: parsing args may do that. */ |
| 3286 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 3297 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
| 3287 | -32768, 32767, &ddebug_dyndbg_module_param_cb); | 3298 | -32768, 32767, unknown_module_param_cb); |
| 3288 | if (err < 0) | 3299 | if (err < 0) |
| 3289 | goto bug_cleanup; | 3300 | goto bug_cleanup; |
| 3290 | 3301 | ||
| @@ -3563,10 +3574,8 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
| 3563 | /* Don't lock: we're in enough trouble already. */ | 3574 | /* Don't lock: we're in enough trouble already. */ |
| 3564 | preempt_disable(); | 3575 | preempt_disable(); |
| 3565 | if ((colon = strchr(name, ':')) != NULL) { | 3576 | if ((colon = strchr(name, ':')) != NULL) { |
| 3566 | *colon = '\0'; | 3577 | if ((mod = find_module_all(name, colon - name, false)) != NULL) |
| 3567 | if ((mod = find_module(name)) != NULL) | ||
| 3568 | ret = mod_find_symname(mod, colon+1); | 3578 | ret = mod_find_symname(mod, colon+1); |
| 3569 | *colon = ':'; | ||
| 3570 | } else { | 3579 | } else { |
| 3571 | list_for_each_entry_rcu(mod, &modules, list) { | 3580 | list_for_each_entry_rcu(mod, &modules, list) { |
| 3572 | if (mod->state == MODULE_STATE_UNFORMED) | 3581 | if (mod->state == MODULE_STATE_UNFORMED) |
