diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-17 13:51:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-17 13:51:22 -0400 |
commit | d190775206d06397a9309421cac5ba2f2c243521 (patch) | |
tree | 60f1fd84e6dd55cefb906382b26eba31b4f1ad71 /kernel/module.c | |
parent | 84f5685230c6aeb427947a2299dcb54c77863df0 (diff) | |
parent | 9be936f4b3a2ec101f54cff9cf1a6abf67263c50 (diff) |
Merge tag 'modules-for-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux
Pull modules updates from Jessica Yu:
"Summary of modules changes for the 4.19 merge window:
- Fix modules kallsyms for livepatch. Livepatch modules can have
SHN_UNDEF symbols in their module symbol tables for later symbol
resolution, but kallsyms shouldn't be returning these symbols
- Some code cleanups and minor reshuffling in load_module() were done
to log the module name when module signature verification fails"
* tag 'modules-for-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
kernel/module: Use kmemdup to replace kmalloc+memcpy
ARM: module: fix modsign build error
modsign: log module name in the event of an error
module: replace VMLINUX_SYMBOL_STR() with __stringify() or string literal
module: print sensible error code
module: setup load info before module_sig_check()
module: make it clear when we're handling the module copy in info->hdr
module: exclude SHN_UNDEF symbols from kallsyms api
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 143 |
1 files changed, 66 insertions, 77 deletions
diff --git a/kernel/module.c b/kernel/module.c index a7615d661910..b046a32520d8 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -307,24 +307,6 @@ int unregister_module_notifier(struct notifier_block *nb) | |||
307 | } | 307 | } |
308 | EXPORT_SYMBOL(unregister_module_notifier); | 308 | EXPORT_SYMBOL(unregister_module_notifier); |
309 | 309 | ||
310 | struct load_info { | ||
311 | const char *name; | ||
312 | Elf_Ehdr *hdr; | ||
313 | unsigned long len; | ||
314 | Elf_Shdr *sechdrs; | ||
315 | char *secstrings, *strtab; | ||
316 | unsigned long symoffs, stroffs; | ||
317 | struct _ddebug *debug; | ||
318 | unsigned int num_debug; | ||
319 | bool sig_ok; | ||
320 | #ifdef CONFIG_KALLSYMS | ||
321 | unsigned long mod_kallsyms_init_off; | ||
322 | #endif | ||
323 | struct { | ||
324 | unsigned int sym, str, mod, vers, info, pcpu; | ||
325 | } index; | ||
326 | }; | ||
327 | |||
328 | /* | 310 | /* |
329 | * We require a truly strong try_module_get(): 0 means success. | 311 | * We require a truly strong try_module_get(): 0 means success. |
330 | * Otherwise an error is returned due to ongoing or failed | 312 | * Otherwise an error is returned due to ongoing or failed |
@@ -1339,14 +1321,12 @@ static inline int check_modstruct_version(const struct load_info *info, | |||
1339 | * locking is necessary -- use preempt_disable() to placate lockdep. | 1321 | * locking is necessary -- use preempt_disable() to placate lockdep. |
1340 | */ | 1322 | */ |
1341 | preempt_disable(); | 1323 | preempt_disable(); |
1342 | if (!find_symbol(VMLINUX_SYMBOL_STR(module_layout), NULL, | 1324 | if (!find_symbol("module_layout", NULL, &crc, true, false)) { |
1343 | &crc, true, false)) { | ||
1344 | preempt_enable(); | 1325 | preempt_enable(); |
1345 | BUG(); | 1326 | BUG(); |
1346 | } | 1327 | } |
1347 | preempt_enable(); | 1328 | preempt_enable(); |
1348 | return check_version(info, VMLINUX_SYMBOL_STR(module_layout), | 1329 | return check_version(info, "module_layout", mod, crc); |
1349 | mod, crc); | ||
1350 | } | 1330 | } |
1351 | 1331 | ||
1352 | /* First part is kernel version, which we ignore if module has crcs. */ | 1332 | /* First part is kernel version, which we ignore if module has crcs. */ |
@@ -2059,21 +2039,19 @@ static int copy_module_elf(struct module *mod, struct load_info *info) | |||
2059 | 2039 | ||
2060 | /* Elf section header table */ | 2040 | /* Elf section header table */ |
2061 | size = sizeof(*info->sechdrs) * info->hdr->e_shnum; | 2041 | size = sizeof(*info->sechdrs) * info->hdr->e_shnum; |
2062 | mod->klp_info->sechdrs = kmalloc(size, GFP_KERNEL); | 2042 | mod->klp_info->sechdrs = kmemdup(info->sechdrs, size, GFP_KERNEL); |
2063 | if (mod->klp_info->sechdrs == NULL) { | 2043 | if (mod->klp_info->sechdrs == NULL) { |
2064 | ret = -ENOMEM; | 2044 | ret = -ENOMEM; |
2065 | goto free_info; | 2045 | goto free_info; |
2066 | } | 2046 | } |
2067 | memcpy(mod->klp_info->sechdrs, info->sechdrs, size); | ||
2068 | 2047 | ||
2069 | /* Elf section name string table */ | 2048 | /* Elf section name string table */ |
2070 | size = info->sechdrs[info->hdr->e_shstrndx].sh_size; | 2049 | size = info->sechdrs[info->hdr->e_shstrndx].sh_size; |
2071 | mod->klp_info->secstrings = kmalloc(size, GFP_KERNEL); | 2050 | mod->klp_info->secstrings = kmemdup(info->secstrings, size, GFP_KERNEL); |
2072 | if (mod->klp_info->secstrings == NULL) { | 2051 | if (mod->klp_info->secstrings == NULL) { |
2073 | ret = -ENOMEM; | 2052 | ret = -ENOMEM; |
2074 | goto free_sechdrs; | 2053 | goto free_sechdrs; |
2075 | } | 2054 | } |
2076 | memcpy(mod->klp_info->secstrings, info->secstrings, size); | ||
2077 | 2055 | ||
2078 | /* Elf symbol section index */ | 2056 | /* Elf symbol section index */ |
2079 | symndx = info->index.sym; | 2057 | symndx = info->index.sym; |
@@ -2282,9 +2260,9 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) | |||
2282 | if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK) | 2260 | if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK) |
2283 | break; | 2261 | break; |
2284 | 2262 | ||
2285 | pr_warn("%s: Unknown symbol %s (err %li)\n", | ||
2286 | mod->name, name, PTR_ERR(ksym)); | ||
2287 | ret = PTR_ERR(ksym) ?: -ENOENT; | 2263 | ret = PTR_ERR(ksym) ?: -ENOENT; |
2264 | pr_warn("%s: Unknown symbol %s (err %d)\n", | ||
2265 | mod->name, name, ret); | ||
2288 | break; | 2266 | break; |
2289 | 2267 | ||
2290 | default: | 2268 | default: |
@@ -2486,7 +2464,11 @@ static char *get_modinfo(struct load_info *info, const char *tag) | |||
2486 | Elf_Shdr *infosec = &info->sechdrs[info->index.info]; | 2464 | Elf_Shdr *infosec = &info->sechdrs[info->index.info]; |
2487 | unsigned long size = infosec->sh_size; | 2465 | unsigned long size = infosec->sh_size; |
2488 | 2466 | ||
2489 | for (p = (char *)infosec->sh_addr; p; p = next_string(p, &size)) { | 2467 | /* |
2468 | * get_modinfo() calls made before rewrite_section_headers() | ||
2469 | * must use sh_offset, as sh_addr isn't set! | ||
2470 | */ | ||
2471 | for (p = (char *)info->hdr + infosec->sh_offset; p; p = next_string(p, &size)) { | ||
2490 | if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') | 2472 | if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') |
2491 | return p + taglen + 1; | 2473 | return p + taglen + 1; |
2492 | } | 2474 | } |
@@ -2774,7 +2756,7 @@ static int module_sig_check(struct load_info *info, int flags) | |||
2774 | memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { | 2756 | memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { |
2775 | /* We truncate the module to discard the signature */ | 2757 | /* We truncate the module to discard the signature */ |
2776 | info->len -= markerlen; | 2758 | info->len -= markerlen; |
2777 | err = mod_verify_sig(mod, &info->len); | 2759 | err = mod_verify_sig(mod, info); |
2778 | } | 2760 | } |
2779 | 2761 | ||
2780 | if (!err) { | 2762 | if (!err) { |
@@ -2926,17 +2908,7 @@ static int rewrite_section_headers(struct load_info *info, int flags) | |||
2926 | } | 2908 | } |
2927 | 2909 | ||
2928 | /* Track but don't keep modinfo and version sections. */ | 2910 | /* Track but don't keep modinfo and version sections. */ |
2929 | if (flags & MODULE_INIT_IGNORE_MODVERSIONS) | ||
2930 | info->index.vers = 0; /* Pretend no __versions section! */ | ||
2931 | else | ||
2932 | info->index.vers = find_sec(info, "__versions"); | ||
2933 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2911 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; |
2934 | |||
2935 | info->index.info = find_sec(info, ".modinfo"); | ||
2936 | if (!info->index.info) | ||
2937 | info->name = "(missing .modinfo section)"; | ||
2938 | else | ||
2939 | info->name = get_modinfo(info, "name"); | ||
2940 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2912 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; |
2941 | 2913 | ||
2942 | return 0; | 2914 | return 0; |
@@ -2947,23 +2919,24 @@ static int rewrite_section_headers(struct load_info *info, int flags) | |||
2947 | * search for module section index etc), and do some basic section | 2919 | * search for module section index etc), and do some basic section |
2948 | * verification. | 2920 | * verification. |
2949 | * | 2921 | * |
2950 | * Return the temporary module pointer (we'll replace it with the final | 2922 | * Set info->mod to the temporary copy of the module in info->hdr. The final one |
2951 | * one when we move the module sections around). | 2923 | * will be allocated in move_module(). |
2952 | */ | 2924 | */ |
2953 | static struct module *setup_load_info(struct load_info *info, int flags) | 2925 | static int setup_load_info(struct load_info *info, int flags) |
2954 | { | 2926 | { |
2955 | unsigned int i; | 2927 | unsigned int i; |
2956 | int err; | ||
2957 | struct module *mod; | ||
2958 | 2928 | ||
2959 | /* Set up the convenience variables */ | 2929 | /* Set up the convenience variables */ |
2960 | info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; | 2930 | info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; |
2961 | info->secstrings = (void *)info->hdr | 2931 | info->secstrings = (void *)info->hdr |
2962 | + info->sechdrs[info->hdr->e_shstrndx].sh_offset; | 2932 | + info->sechdrs[info->hdr->e_shstrndx].sh_offset; |
2963 | 2933 | ||
2964 | err = rewrite_section_headers(info, flags); | 2934 | /* Try to find a name early so we can log errors with a module name */ |
2965 | if (err) | 2935 | info->index.info = find_sec(info, ".modinfo"); |
2966 | return ERR_PTR(err); | 2936 | if (!info->index.info) |
2937 | info->name = "(missing .modinfo section)"; | ||
2938 | else | ||
2939 | info->name = get_modinfo(info, "name"); | ||
2967 | 2940 | ||
2968 | /* Find internal symbols and strings. */ | 2941 | /* Find internal symbols and strings. */ |
2969 | for (i = 1; i < info->hdr->e_shnum; i++) { | 2942 | for (i = 1; i < info->hdr->e_shnum; i++) { |
@@ -2976,34 +2949,35 @@ static struct module *setup_load_info(struct load_info *info, int flags) | |||
2976 | } | 2949 | } |
2977 | } | 2950 | } |
2978 | 2951 | ||
2952 | if (info->index.sym == 0) { | ||
2953 | pr_warn("%s: module has no symbols (stripped?)\n", info->name); | ||
2954 | return -ENOEXEC; | ||
2955 | } | ||
2956 | |||
2979 | info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); | 2957 | info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); |
2980 | if (!info->index.mod) { | 2958 | if (!info->index.mod) { |
2981 | pr_warn("%s: No module found in object\n", | 2959 | pr_warn("%s: No module found in object\n", |
2982 | info->name ?: "(missing .modinfo name field)"); | 2960 | info->name ?: "(missing .modinfo name field)"); |
2983 | return ERR_PTR(-ENOEXEC); | 2961 | return -ENOEXEC; |
2984 | } | 2962 | } |
2985 | /* This is temporary: point mod into copy of data. */ | 2963 | /* This is temporary: point mod into copy of data. */ |
2986 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; | 2964 | info->mod = (void *)info->hdr + info->sechdrs[info->index.mod].sh_offset; |
2987 | 2965 | ||
2988 | /* | 2966 | /* |
2989 | * If we didn't load the .modinfo 'name' field, fall back to | 2967 | * If we didn't load the .modinfo 'name' field earlier, fall back to |
2990 | * on-disk struct mod 'name' field. | 2968 | * on-disk struct mod 'name' field. |
2991 | */ | 2969 | */ |
2992 | if (!info->name) | 2970 | if (!info->name) |
2993 | info->name = mod->name; | 2971 | info->name = info->mod->name; |
2994 | 2972 | ||
2995 | if (info->index.sym == 0) { | 2973 | if (flags & MODULE_INIT_IGNORE_MODVERSIONS) |
2996 | pr_warn("%s: module has no symbols (stripped?)\n", info->name); | 2974 | info->index.vers = 0; /* Pretend no __versions section! */ |
2997 | return ERR_PTR(-ENOEXEC); | 2975 | else |
2998 | } | 2976 | info->index.vers = find_sec(info, "__versions"); |
2999 | 2977 | ||
3000 | info->index.pcpu = find_pcpusec(info); | 2978 | info->index.pcpu = find_pcpusec(info); |
3001 | 2979 | ||
3002 | /* Check module struct version now, before we try to use module. */ | 2980 | return 0; |
3003 | if (!check_modstruct_version(info, mod)) | ||
3004 | return ERR_PTR(-ENOEXEC); | ||
3005 | |||
3006 | return mod; | ||
3007 | } | 2981 | } |
3008 | 2982 | ||
3009 | static int check_modinfo(struct module *mod, struct load_info *info, int flags) | 2983 | static int check_modinfo(struct module *mod, struct load_info *info, int flags) |
@@ -3298,25 +3272,17 @@ core_param(module_blacklist, module_blacklist, charp, 0400); | |||
3298 | 3272 | ||
3299 | static struct module *layout_and_allocate(struct load_info *info, int flags) | 3273 | static struct module *layout_and_allocate(struct load_info *info, int flags) |
3300 | { | 3274 | { |
3301 | /* Module within temporary copy. */ | ||
3302 | struct module *mod; | 3275 | struct module *mod; |
3303 | unsigned int ndx; | 3276 | unsigned int ndx; |
3304 | int err; | 3277 | int err; |
3305 | 3278 | ||
3306 | mod = setup_load_info(info, flags); | 3279 | err = check_modinfo(info->mod, info, flags); |
3307 | if (IS_ERR(mod)) | ||
3308 | return mod; | ||
3309 | |||
3310 | if (blacklisted(info->name)) | ||
3311 | return ERR_PTR(-EPERM); | ||
3312 | |||
3313 | err = check_modinfo(mod, info, flags); | ||
3314 | if (err) | 3280 | if (err) |
3315 | return ERR_PTR(err); | 3281 | return ERR_PTR(err); |
3316 | 3282 | ||
3317 | /* Allow arches to frob section contents and sizes. */ | 3283 | /* Allow arches to frob section contents and sizes. */ |
3318 | err = module_frob_arch_sections(info->hdr, info->sechdrs, | 3284 | err = module_frob_arch_sections(info->hdr, info->sechdrs, |
3319 | info->secstrings, mod); | 3285 | info->secstrings, info->mod); |
3320 | if (err < 0) | 3286 | if (err < 0) |
3321 | return ERR_PTR(err); | 3287 | return ERR_PTR(err); |
3322 | 3288 | ||
@@ -3335,11 +3301,11 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
3335 | /* Determine total sizes, and put offsets in sh_entsize. For now | 3301 | /* Determine total sizes, and put offsets in sh_entsize. For now |
3336 | this is done generically; there doesn't appear to be any | 3302 | this is done generically; there doesn't appear to be any |
3337 | special cases for the architectures. */ | 3303 | special cases for the architectures. */ |
3338 | layout_sections(mod, info); | 3304 | layout_sections(info->mod, info); |
3339 | layout_symtab(mod, info); | 3305 | layout_symtab(info->mod, info); |
3340 | 3306 | ||
3341 | /* Allocate and move to the final place */ | 3307 | /* Allocate and move to the final place */ |
3342 | err = move_module(mod, info); | 3308 | err = move_module(info->mod, info); |
3343 | if (err) | 3309 | if (err) |
3344 | return ERR_PTR(err); | 3310 | return ERR_PTR(err); |
3345 | 3311 | ||
@@ -3657,17 +3623,36 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3657 | int flags) | 3623 | int flags) |
3658 | { | 3624 | { |
3659 | struct module *mod; | 3625 | struct module *mod; |
3660 | long err; | 3626 | long err = 0; |
3661 | char *after_dashes; | 3627 | char *after_dashes; |
3662 | 3628 | ||
3629 | err = elf_header_check(info); | ||
3630 | if (err) | ||
3631 | goto free_copy; | ||
3632 | |||
3633 | err = setup_load_info(info, flags); | ||
3634 | if (err) | ||
3635 | goto free_copy; | ||
3636 | |||
3637 | if (blacklisted(info->name)) { | ||
3638 | err = -EPERM; | ||
3639 | goto free_copy; | ||
3640 | } | ||
3641 | |||
3663 | err = module_sig_check(info, flags); | 3642 | err = module_sig_check(info, flags); |
3664 | if (err) | 3643 | if (err) |
3665 | goto free_copy; | 3644 | goto free_copy; |
3666 | 3645 | ||
3667 | err = elf_header_check(info); | 3646 | err = rewrite_section_headers(info, flags); |
3668 | if (err) | 3647 | if (err) |
3669 | goto free_copy; | 3648 | goto free_copy; |
3670 | 3649 | ||
3650 | /* Check module struct version now, before we try to use module. */ | ||
3651 | if (!check_modstruct_version(info, info->mod)) { | ||
3652 | err = -ENOEXEC; | ||
3653 | goto free_copy; | ||
3654 | } | ||
3655 | |||
3671 | /* Figure out module layout, and allocate all the memory. */ | 3656 | /* Figure out module layout, and allocate all the memory. */ |
3672 | mod = layout_and_allocate(info, flags); | 3657 | mod = layout_and_allocate(info, flags); |
3673 | if (IS_ERR(mod)) { | 3658 | if (IS_ERR(mod)) { |
@@ -4067,7 +4052,7 @@ static unsigned long mod_find_symname(struct module *mod, const char *name) | |||
4067 | 4052 | ||
4068 | for (i = 0; i < kallsyms->num_symtab; i++) | 4053 | for (i = 0; i < kallsyms->num_symtab; i++) |
4069 | if (strcmp(name, symname(kallsyms, i)) == 0 && | 4054 | if (strcmp(name, symname(kallsyms, i)) == 0 && |
4070 | kallsyms->symtab[i].st_info != 'U') | 4055 | kallsyms->symtab[i].st_shndx != SHN_UNDEF) |
4071 | return kallsyms->symtab[i].st_value; | 4056 | return kallsyms->symtab[i].st_value; |
4072 | return 0; | 4057 | return 0; |
4073 | } | 4058 | } |
@@ -4113,6 +4098,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, | |||
4113 | if (mod->state == MODULE_STATE_UNFORMED) | 4098 | if (mod->state == MODULE_STATE_UNFORMED) |
4114 | continue; | 4099 | continue; |
4115 | for (i = 0; i < kallsyms->num_symtab; i++) { | 4100 | for (i = 0; i < kallsyms->num_symtab; i++) { |
4101 | |||
4102 | if (kallsyms->symtab[i].st_shndx == SHN_UNDEF) | ||
4103 | continue; | ||
4104 | |||
4116 | ret = fn(data, symname(kallsyms, i), | 4105 | ret = fn(data, symname(kallsyms, i), |
4117 | mod, kallsyms->symtab[i].st_value); | 4106 | mod, kallsyms->symtab[i].st_value); |
4118 | if (ret != 0) | 4107 | if (ret != 0) |