diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-27 15:08:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-27 15:08:33 -0500 |
commit | 7f9f852c75e7d776b078813586c76a2bc7dca993 (patch) | |
tree | 1870d8ce5b3a6b3b964a3d9cddf2c75e896fc61a /kernel/module.c | |
parent | 3f03bf93947fa2a2b84fac56e93c65d4fffed7f1 (diff) | |
parent | 93d77e7f1410c366050d6035dcba1a5167c7cf0b (diff) |
Merge tag 'modules-for-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux
Pull modules updates from Jessica Yu:
- Some modules-related kallsyms cleanups and a kallsyms fix for ARM.
- Include keys from the secondary keyring in module signature
verification.
* tag 'modules-for-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
ARM: module: Fix function kallsyms on Thumb-2
module: Overwrite st_size instead of st_info
module: make it clearer when we're handling kallsyms symbols vs exported symbols
modsign: use all trusted keys to verify module signature
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 123 |
1 files changed, 72 insertions, 51 deletions
diff --git a/kernel/module.c b/kernel/module.c index 99b46c32d579..339b3cd39dd4 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -495,9 +495,9 @@ struct find_symbol_arg { | |||
495 | const struct kernel_symbol *sym; | 495 | const struct kernel_symbol *sym; |
496 | }; | 496 | }; |
497 | 497 | ||
498 | static bool check_symbol(const struct symsearch *syms, | 498 | static bool check_exported_symbol(const struct symsearch *syms, |
499 | struct module *owner, | 499 | struct module *owner, |
500 | unsigned int symnum, void *data) | 500 | unsigned int symnum, void *data) |
501 | { | 501 | { |
502 | struct find_symbol_arg *fsa = data; | 502 | struct find_symbol_arg *fsa = data; |
503 | 503 | ||
@@ -555,9 +555,9 @@ static int cmp_name(const void *va, const void *vb) | |||
555 | return strcmp(a, kernel_symbol_name(b)); | 555 | return strcmp(a, kernel_symbol_name(b)); |
556 | } | 556 | } |
557 | 557 | ||
558 | static bool find_symbol_in_section(const struct symsearch *syms, | 558 | static bool find_exported_symbol_in_section(const struct symsearch *syms, |
559 | struct module *owner, | 559 | struct module *owner, |
560 | void *data) | 560 | void *data) |
561 | { | 561 | { |
562 | struct find_symbol_arg *fsa = data; | 562 | struct find_symbol_arg *fsa = data; |
563 | struct kernel_symbol *sym; | 563 | struct kernel_symbol *sym; |
@@ -565,13 +565,14 @@ static bool find_symbol_in_section(const struct symsearch *syms, | |||
565 | sym = bsearch(fsa->name, syms->start, syms->stop - syms->start, | 565 | sym = bsearch(fsa->name, syms->start, syms->stop - syms->start, |
566 | sizeof(struct kernel_symbol), cmp_name); | 566 | sizeof(struct kernel_symbol), cmp_name); |
567 | 567 | ||
568 | if (sym != NULL && check_symbol(syms, owner, sym - syms->start, data)) | 568 | if (sym != NULL && check_exported_symbol(syms, owner, |
569 | sym - syms->start, data)) | ||
569 | return true; | 570 | return true; |
570 | 571 | ||
571 | return false; | 572 | return false; |
572 | } | 573 | } |
573 | 574 | ||
574 | /* Find a symbol and return it, along with, (optional) crc and | 575 | /* Find an exported symbol and return it, along with, (optional) crc and |
575 | * (optional) module which owns it. Needs preempt disabled or module_mutex. */ | 576 | * (optional) module which owns it. Needs preempt disabled or module_mutex. */ |
576 | const struct kernel_symbol *find_symbol(const char *name, | 577 | const struct kernel_symbol *find_symbol(const char *name, |
577 | struct module **owner, | 578 | struct module **owner, |
@@ -585,7 +586,7 @@ const struct kernel_symbol *find_symbol(const char *name, | |||
585 | fsa.gplok = gplok; | 586 | fsa.gplok = gplok; |
586 | fsa.warn = warn; | 587 | fsa.warn = warn; |
587 | 588 | ||
588 | if (each_symbol_section(find_symbol_in_section, &fsa)) { | 589 | if (each_symbol_section(find_exported_symbol_in_section, &fsa)) { |
589 | if (owner) | 590 | if (owner) |
590 | *owner = fsa.owner; | 591 | *owner = fsa.owner; |
591 | if (crc) | 592 | if (crc) |
@@ -2198,7 +2199,7 @@ EXPORT_SYMBOL_GPL(__symbol_get); | |||
2198 | * | 2199 | * |
2199 | * You must hold the module_mutex. | 2200 | * You must hold the module_mutex. |
2200 | */ | 2201 | */ |
2201 | static int verify_export_symbols(struct module *mod) | 2202 | static int verify_exported_symbols(struct module *mod) |
2202 | { | 2203 | { |
2203 | unsigned int i; | 2204 | unsigned int i; |
2204 | struct module *owner; | 2205 | struct module *owner; |
@@ -2519,10 +2520,10 @@ static void free_modinfo(struct module *mod) | |||
2519 | 2520 | ||
2520 | #ifdef CONFIG_KALLSYMS | 2521 | #ifdef CONFIG_KALLSYMS |
2521 | 2522 | ||
2522 | /* lookup symbol in given range of kernel_symbols */ | 2523 | /* Lookup exported symbol in given range of kernel_symbols */ |
2523 | static const struct kernel_symbol *lookup_symbol(const char *name, | 2524 | static const struct kernel_symbol *lookup_exported_symbol(const char *name, |
2524 | const struct kernel_symbol *start, | 2525 | const struct kernel_symbol *start, |
2525 | const struct kernel_symbol *stop) | 2526 | const struct kernel_symbol *stop) |
2526 | { | 2527 | { |
2527 | return bsearch(name, start, stop - start, | 2528 | return bsearch(name, start, stop - start, |
2528 | sizeof(struct kernel_symbol), cmp_name); | 2529 | sizeof(struct kernel_symbol), cmp_name); |
@@ -2533,9 +2534,10 @@ static int is_exported(const char *name, unsigned long value, | |||
2533 | { | 2534 | { |
2534 | const struct kernel_symbol *ks; | 2535 | const struct kernel_symbol *ks; |
2535 | if (!mod) | 2536 | if (!mod) |
2536 | ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab); | 2537 | ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab); |
2537 | else | 2538 | else |
2538 | ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms); | 2539 | ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms); |
2540 | |||
2539 | return ks != NULL && kernel_symbol_value(ks) == value; | 2541 | return ks != NULL && kernel_symbol_value(ks) == value; |
2540 | } | 2542 | } |
2541 | 2543 | ||
@@ -2682,7 +2684,7 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) | |||
2682 | 2684 | ||
2683 | /* Set types up while we still have access to sections. */ | 2685 | /* Set types up while we still have access to sections. */ |
2684 | for (i = 0; i < mod->kallsyms->num_symtab; i++) | 2686 | for (i = 0; i < mod->kallsyms->num_symtab; i++) |
2685 | mod->kallsyms->symtab[i].st_info | 2687 | mod->kallsyms->symtab[i].st_size |
2686 | = elf_type(&mod->kallsyms->symtab[i], info); | 2688 | = elf_type(&mod->kallsyms->symtab[i], info); |
2687 | 2689 | ||
2688 | /* Now populate the cut down core kallsyms for after init. */ | 2690 | /* Now populate the cut down core kallsyms for after init. */ |
@@ -3592,7 +3594,7 @@ static int complete_formation(struct module *mod, struct load_info *info) | |||
3592 | mutex_lock(&module_mutex); | 3594 | mutex_lock(&module_mutex); |
3593 | 3595 | ||
3594 | /* Find duplicate symbols (must be called under lock). */ | 3596 | /* Find duplicate symbols (must be called under lock). */ |
3595 | err = verify_export_symbols(mod); | 3597 | err = verify_exported_symbols(mod); |
3596 | if (err < 0) | 3598 | if (err < 0) |
3597 | goto out; | 3599 | goto out; |
3598 | 3600 | ||
@@ -3911,18 +3913,22 @@ static inline int is_arm_mapping_symbol(const char *str) | |||
3911 | && (str[2] == '\0' || str[2] == '.'); | 3913 | && (str[2] == '\0' || str[2] == '.'); |
3912 | } | 3914 | } |
3913 | 3915 | ||
3914 | static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum) | 3916 | static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum) |
3915 | { | 3917 | { |
3916 | return kallsyms->strtab + kallsyms->symtab[symnum].st_name; | 3918 | return kallsyms->strtab + kallsyms->symtab[symnum].st_name; |
3917 | } | 3919 | } |
3918 | 3920 | ||
3919 | static const char *get_ksymbol(struct module *mod, | 3921 | /* |
3920 | unsigned long addr, | 3922 | * Given a module and address, find the corresponding symbol and return its name |
3921 | unsigned long *size, | 3923 | * while providing its size and offset if needed. |
3922 | unsigned long *offset) | 3924 | */ |
3925 | static const char *find_kallsyms_symbol(struct module *mod, | ||
3926 | unsigned long addr, | ||
3927 | unsigned long *size, | ||
3928 | unsigned long *offset) | ||
3923 | { | 3929 | { |
3924 | unsigned int i, best = 0; | 3930 | unsigned int i, best = 0; |
3925 | unsigned long nextval; | 3931 | unsigned long nextval, bestval; |
3926 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); | 3932 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); |
3927 | 3933 | ||
3928 | /* At worse, next value is at end of module */ | 3934 | /* At worse, next value is at end of module */ |
@@ -3931,34 +3937,40 @@ static const char *get_ksymbol(struct module *mod, | |||
3931 | else | 3937 | else |
3932 | nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size; | 3938 | nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size; |
3933 | 3939 | ||
3940 | bestval = kallsyms_symbol_value(&kallsyms->symtab[best]); | ||
3941 | |||
3934 | /* Scan for closest preceding symbol, and next symbol. (ELF | 3942 | /* Scan for closest preceding symbol, and next symbol. (ELF |
3935 | starts real symbols at 1). */ | 3943 | starts real symbols at 1). */ |
3936 | for (i = 1; i < kallsyms->num_symtab; i++) { | 3944 | for (i = 1; i < kallsyms->num_symtab; i++) { |
3937 | if (kallsyms->symtab[i].st_shndx == SHN_UNDEF) | 3945 | const Elf_Sym *sym = &kallsyms->symtab[i]; |
3946 | unsigned long thisval = kallsyms_symbol_value(sym); | ||
3947 | |||
3948 | if (sym->st_shndx == SHN_UNDEF) | ||
3938 | continue; | 3949 | continue; |
3939 | 3950 | ||
3940 | /* We ignore unnamed symbols: they're uninformative | 3951 | /* We ignore unnamed symbols: they're uninformative |
3941 | * and inserted at a whim. */ | 3952 | * and inserted at a whim. */ |
3942 | if (*symname(kallsyms, i) == '\0' | 3953 | if (*kallsyms_symbol_name(kallsyms, i) == '\0' |
3943 | || is_arm_mapping_symbol(symname(kallsyms, i))) | 3954 | || is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i))) |
3944 | continue; | 3955 | continue; |
3945 | 3956 | ||
3946 | if (kallsyms->symtab[i].st_value <= addr | 3957 | if (thisval <= addr && thisval > bestval) { |
3947 | && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value) | ||
3948 | best = i; | 3958 | best = i; |
3949 | if (kallsyms->symtab[i].st_value > addr | 3959 | bestval = thisval; |
3950 | && kallsyms->symtab[i].st_value < nextval) | 3960 | } |
3951 | nextval = kallsyms->symtab[i].st_value; | 3961 | if (thisval > addr && thisval < nextval) |
3962 | nextval = thisval; | ||
3952 | } | 3963 | } |
3953 | 3964 | ||
3954 | if (!best) | 3965 | if (!best) |
3955 | return NULL; | 3966 | return NULL; |
3956 | 3967 | ||
3957 | if (size) | 3968 | if (size) |
3958 | *size = nextval - kallsyms->symtab[best].st_value; | 3969 | *size = nextval - bestval; |
3959 | if (offset) | 3970 | if (offset) |
3960 | *offset = addr - kallsyms->symtab[best].st_value; | 3971 | *offset = addr - bestval; |
3961 | return symname(kallsyms, best); | 3972 | |
3973 | return kallsyms_symbol_name(kallsyms, best); | ||
3962 | } | 3974 | } |
3963 | 3975 | ||
3964 | void * __weak dereference_module_function_descriptor(struct module *mod, | 3976 | void * __weak dereference_module_function_descriptor(struct module *mod, |
@@ -3983,7 +3995,8 @@ const char *module_address_lookup(unsigned long addr, | |||
3983 | if (mod) { | 3995 | if (mod) { |
3984 | if (modname) | 3996 | if (modname) |
3985 | *modname = mod->name; | 3997 | *modname = mod->name; |
3986 | ret = get_ksymbol(mod, addr, size, offset); | 3998 | |
3999 | ret = find_kallsyms_symbol(mod, addr, size, offset); | ||
3987 | } | 4000 | } |
3988 | /* Make a copy in here where it's safe */ | 4001 | /* Make a copy in here where it's safe */ |
3989 | if (ret) { | 4002 | if (ret) { |
@@ -4006,9 +4019,10 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
4006 | if (within_module(addr, mod)) { | 4019 | if (within_module(addr, mod)) { |
4007 | const char *sym; | 4020 | const char *sym; |
4008 | 4021 | ||
4009 | sym = get_ksymbol(mod, addr, NULL, NULL); | 4022 | sym = find_kallsyms_symbol(mod, addr, NULL, NULL); |
4010 | if (!sym) | 4023 | if (!sym) |
4011 | goto out; | 4024 | goto out; |
4025 | |||
4012 | strlcpy(symname, sym, KSYM_NAME_LEN); | 4026 | strlcpy(symname, sym, KSYM_NAME_LEN); |
4013 | preempt_enable(); | 4027 | preempt_enable(); |
4014 | return 0; | 4028 | return 0; |
@@ -4031,7 +4045,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
4031 | if (within_module(addr, mod)) { | 4045 | if (within_module(addr, mod)) { |
4032 | const char *sym; | 4046 | const char *sym; |
4033 | 4047 | ||
4034 | sym = get_ksymbol(mod, addr, size, offset); | 4048 | sym = find_kallsyms_symbol(mod, addr, size, offset); |
4035 | if (!sym) | 4049 | if (!sym) |
4036 | goto out; | 4050 | goto out; |
4037 | if (modname) | 4051 | if (modname) |
@@ -4060,9 +4074,11 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
4060 | continue; | 4074 | continue; |
4061 | kallsyms = rcu_dereference_sched(mod->kallsyms); | 4075 | kallsyms = rcu_dereference_sched(mod->kallsyms); |
4062 | if (symnum < kallsyms->num_symtab) { | 4076 | if (symnum < kallsyms->num_symtab) { |
4063 | *value = kallsyms->symtab[symnum].st_value; | 4077 | const Elf_Sym *sym = &kallsyms->symtab[symnum]; |
4064 | *type = kallsyms->symtab[symnum].st_info; | 4078 | |
4065 | strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN); | 4079 | *value = kallsyms_symbol_value(sym); |
4080 | *type = sym->st_size; | ||
4081 | strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN); | ||
4066 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); | 4082 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); |
4067 | *exported = is_exported(name, *value, mod); | 4083 | *exported = is_exported(name, *value, mod); |
4068 | preempt_enable(); | 4084 | preempt_enable(); |
@@ -4074,15 +4090,19 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
4074 | return -ERANGE; | 4090 | return -ERANGE; |
4075 | } | 4091 | } |
4076 | 4092 | ||
4077 | static unsigned long mod_find_symname(struct module *mod, const char *name) | 4093 | /* Given a module and name of symbol, find and return the symbol's value */ |
4094 | static unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name) | ||
4078 | { | 4095 | { |
4079 | unsigned int i; | 4096 | unsigned int i; |
4080 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); | 4097 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); |
4081 | 4098 | ||
4082 | for (i = 0; i < kallsyms->num_symtab; i++) | 4099 | for (i = 0; i < kallsyms->num_symtab; i++) { |
4083 | if (strcmp(name, symname(kallsyms, i)) == 0 && | 4100 | const Elf_Sym *sym = &kallsyms->symtab[i]; |
4084 | kallsyms->symtab[i].st_shndx != SHN_UNDEF) | 4101 | |
4085 | return kallsyms->symtab[i].st_value; | 4102 | if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 && |
4103 | sym->st_shndx != SHN_UNDEF) | ||
4104 | return kallsyms_symbol_value(sym); | ||
4105 | } | ||
4086 | return 0; | 4106 | return 0; |
4087 | } | 4107 | } |
4088 | 4108 | ||
@@ -4097,12 +4117,12 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
4097 | preempt_disable(); | 4117 | preempt_disable(); |
4098 | if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { | 4118 | if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { |
4099 | if ((mod = find_module_all(name, colon - name, false)) != NULL) | 4119 | if ((mod = find_module_all(name, colon - name, false)) != NULL) |
4100 | ret = mod_find_symname(mod, colon+1); | 4120 | ret = find_kallsyms_symbol_value(mod, colon+1); |
4101 | } else { | 4121 | } else { |
4102 | list_for_each_entry_rcu(mod, &modules, list) { | 4122 | list_for_each_entry_rcu(mod, &modules, list) { |
4103 | if (mod->state == MODULE_STATE_UNFORMED) | 4123 | if (mod->state == MODULE_STATE_UNFORMED) |
4104 | continue; | 4124 | continue; |
4105 | if ((ret = mod_find_symname(mod, name)) != 0) | 4125 | if ((ret = find_kallsyms_symbol_value(mod, name)) != 0) |
4106 | break; | 4126 | break; |
4107 | } | 4127 | } |
4108 | } | 4128 | } |
@@ -4127,12 +4147,13 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, | |||
4127 | if (mod->state == MODULE_STATE_UNFORMED) | 4147 | if (mod->state == MODULE_STATE_UNFORMED) |
4128 | continue; | 4148 | continue; |
4129 | for (i = 0; i < kallsyms->num_symtab; i++) { | 4149 | for (i = 0; i < kallsyms->num_symtab; i++) { |
4150 | const Elf_Sym *sym = &kallsyms->symtab[i]; | ||
4130 | 4151 | ||
4131 | if (kallsyms->symtab[i].st_shndx == SHN_UNDEF) | 4152 | if (sym->st_shndx == SHN_UNDEF) |
4132 | continue; | 4153 | continue; |
4133 | 4154 | ||
4134 | ret = fn(data, symname(kallsyms, i), | 4155 | ret = fn(data, kallsyms_symbol_name(kallsyms, i), |
4135 | mod, kallsyms->symtab[i].st_value); | 4156 | mod, kallsyms_symbol_value(sym)); |
4136 | if (ret != 0) | 4157 | if (ret != 0) |
4137 | return ret; | 4158 | return ret; |
4138 | } | 4159 | } |