diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 134 |
1 files changed, 81 insertions, 53 deletions
diff --git a/kernel/module.c b/kernel/module.c index 99b46c32d579..fcbc0128810b 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) |
@@ -1207,8 +1208,10 @@ static ssize_t store_uevent(struct module_attribute *mattr, | |||
1207 | struct module_kobject *mk, | 1208 | struct module_kobject *mk, |
1208 | const char *buffer, size_t count) | 1209 | const char *buffer, size_t count) |
1209 | { | 1210 | { |
1210 | kobject_synth_uevent(&mk->kobj, buffer, count); | 1211 | int rc; |
1211 | return count; | 1212 | |
1213 | rc = kobject_synth_uevent(&mk->kobj, buffer, count); | ||
1214 | return rc ? rc : count; | ||
1212 | } | 1215 | } |
1213 | 1216 | ||
1214 | struct module_attribute module_uevent = | 1217 | struct module_attribute module_uevent = |
@@ -2198,7 +2201,7 @@ EXPORT_SYMBOL_GPL(__symbol_get); | |||
2198 | * | 2201 | * |
2199 | * You must hold the module_mutex. | 2202 | * You must hold the module_mutex. |
2200 | */ | 2203 | */ |
2201 | static int verify_export_symbols(struct module *mod) | 2204 | static int verify_exported_symbols(struct module *mod) |
2202 | { | 2205 | { |
2203 | unsigned int i; | 2206 | unsigned int i; |
2204 | struct module *owner; | 2207 | struct module *owner; |
@@ -2519,10 +2522,10 @@ static void free_modinfo(struct module *mod) | |||
2519 | 2522 | ||
2520 | #ifdef CONFIG_KALLSYMS | 2523 | #ifdef CONFIG_KALLSYMS |
2521 | 2524 | ||
2522 | /* lookup symbol in given range of kernel_symbols */ | 2525 | /* Lookup exported symbol in given range of kernel_symbols */ |
2523 | static const struct kernel_symbol *lookup_symbol(const char *name, | 2526 | static const struct kernel_symbol *lookup_exported_symbol(const char *name, |
2524 | const struct kernel_symbol *start, | 2527 | const struct kernel_symbol *start, |
2525 | const struct kernel_symbol *stop) | 2528 | const struct kernel_symbol *stop) |
2526 | { | 2529 | { |
2527 | return bsearch(name, start, stop - start, | 2530 | return bsearch(name, start, stop - start, |
2528 | sizeof(struct kernel_symbol), cmp_name); | 2531 | sizeof(struct kernel_symbol), cmp_name); |
@@ -2533,9 +2536,10 @@ static int is_exported(const char *name, unsigned long value, | |||
2533 | { | 2536 | { |
2534 | const struct kernel_symbol *ks; | 2537 | const struct kernel_symbol *ks; |
2535 | if (!mod) | 2538 | if (!mod) |
2536 | ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab); | 2539 | ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab); |
2537 | else | 2540 | else |
2538 | ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms); | 2541 | ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms); |
2542 | |||
2539 | return ks != NULL && kernel_symbol_value(ks) == value; | 2543 | return ks != NULL && kernel_symbol_value(ks) == value; |
2540 | } | 2544 | } |
2541 | 2545 | ||
@@ -2682,7 +2686,7 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) | |||
2682 | 2686 | ||
2683 | /* Set types up while we still have access to sections. */ | 2687 | /* Set types up while we still have access to sections. */ |
2684 | for (i = 0; i < mod->kallsyms->num_symtab; i++) | 2688 | for (i = 0; i < mod->kallsyms->num_symtab; i++) |
2685 | mod->kallsyms->symtab[i].st_info | 2689 | mod->kallsyms->symtab[i].st_size |
2686 | = elf_type(&mod->kallsyms->symtab[i], info); | 2690 | = elf_type(&mod->kallsyms->symtab[i], info); |
2687 | 2691 | ||
2688 | /* Now populate the cut down core kallsyms for after init. */ | 2692 | /* Now populate the cut down core kallsyms for after init. */ |
@@ -3093,6 +3097,11 @@ static int find_module_sections(struct module *mod, struct load_info *info) | |||
3093 | sizeof(*mod->tracepoints_ptrs), | 3097 | sizeof(*mod->tracepoints_ptrs), |
3094 | &mod->num_tracepoints); | 3098 | &mod->num_tracepoints); |
3095 | #endif | 3099 | #endif |
3100 | #ifdef CONFIG_BPF_EVENTS | ||
3101 | mod->bpf_raw_events = section_objs(info, "__bpf_raw_tp_map", | ||
3102 | sizeof(*mod->bpf_raw_events), | ||
3103 | &mod->num_bpf_raw_events); | ||
3104 | #endif | ||
3096 | #ifdef HAVE_JUMP_LABEL | 3105 | #ifdef HAVE_JUMP_LABEL |
3097 | mod->jump_entries = section_objs(info, "__jump_table", | 3106 | mod->jump_entries = section_objs(info, "__jump_table", |
3098 | sizeof(*mod->jump_entries), | 3107 | sizeof(*mod->jump_entries), |
@@ -3592,7 +3601,7 @@ static int complete_formation(struct module *mod, struct load_info *info) | |||
3592 | mutex_lock(&module_mutex); | 3601 | mutex_lock(&module_mutex); |
3593 | 3602 | ||
3594 | /* Find duplicate symbols (must be called under lock). */ | 3603 | /* Find duplicate symbols (must be called under lock). */ |
3595 | err = verify_export_symbols(mod); | 3604 | err = verify_exported_symbols(mod); |
3596 | if (err < 0) | 3605 | if (err < 0) |
3597 | goto out; | 3606 | goto out; |
3598 | 3607 | ||
@@ -3911,18 +3920,22 @@ static inline int is_arm_mapping_symbol(const char *str) | |||
3911 | && (str[2] == '\0' || str[2] == '.'); | 3920 | && (str[2] == '\0' || str[2] == '.'); |
3912 | } | 3921 | } |
3913 | 3922 | ||
3914 | static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum) | 3923 | static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum) |
3915 | { | 3924 | { |
3916 | return kallsyms->strtab + kallsyms->symtab[symnum].st_name; | 3925 | return kallsyms->strtab + kallsyms->symtab[symnum].st_name; |
3917 | } | 3926 | } |
3918 | 3927 | ||
3919 | static const char *get_ksymbol(struct module *mod, | 3928 | /* |
3920 | unsigned long addr, | 3929 | * Given a module and address, find the corresponding symbol and return its name |
3921 | unsigned long *size, | 3930 | * while providing its size and offset if needed. |
3922 | unsigned long *offset) | 3931 | */ |
3932 | static const char *find_kallsyms_symbol(struct module *mod, | ||
3933 | unsigned long addr, | ||
3934 | unsigned long *size, | ||
3935 | unsigned long *offset) | ||
3923 | { | 3936 | { |
3924 | unsigned int i, best = 0; | 3937 | unsigned int i, best = 0; |
3925 | unsigned long nextval; | 3938 | unsigned long nextval, bestval; |
3926 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); | 3939 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); |
3927 | 3940 | ||
3928 | /* At worse, next value is at end of module */ | 3941 | /* At worse, next value is at end of module */ |
@@ -3931,34 +3944,40 @@ static const char *get_ksymbol(struct module *mod, | |||
3931 | else | 3944 | else |
3932 | nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size; | 3945 | nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size; |
3933 | 3946 | ||
3947 | bestval = kallsyms_symbol_value(&kallsyms->symtab[best]); | ||
3948 | |||
3934 | /* Scan for closest preceding symbol, and next symbol. (ELF | 3949 | /* Scan for closest preceding symbol, and next symbol. (ELF |
3935 | starts real symbols at 1). */ | 3950 | starts real symbols at 1). */ |
3936 | for (i = 1; i < kallsyms->num_symtab; i++) { | 3951 | for (i = 1; i < kallsyms->num_symtab; i++) { |
3937 | if (kallsyms->symtab[i].st_shndx == SHN_UNDEF) | 3952 | const Elf_Sym *sym = &kallsyms->symtab[i]; |
3953 | unsigned long thisval = kallsyms_symbol_value(sym); | ||
3954 | |||
3955 | if (sym->st_shndx == SHN_UNDEF) | ||
3938 | continue; | 3956 | continue; |
3939 | 3957 | ||
3940 | /* We ignore unnamed symbols: they're uninformative | 3958 | /* We ignore unnamed symbols: they're uninformative |
3941 | * and inserted at a whim. */ | 3959 | * and inserted at a whim. */ |
3942 | if (*symname(kallsyms, i) == '\0' | 3960 | if (*kallsyms_symbol_name(kallsyms, i) == '\0' |
3943 | || is_arm_mapping_symbol(symname(kallsyms, i))) | 3961 | || is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i))) |
3944 | continue; | 3962 | continue; |
3945 | 3963 | ||
3946 | if (kallsyms->symtab[i].st_value <= addr | 3964 | if (thisval <= addr && thisval > bestval) { |
3947 | && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value) | ||
3948 | best = i; | 3965 | best = i; |
3949 | if (kallsyms->symtab[i].st_value > addr | 3966 | bestval = thisval; |
3950 | && kallsyms->symtab[i].st_value < nextval) | 3967 | } |
3951 | nextval = kallsyms->symtab[i].st_value; | 3968 | if (thisval > addr && thisval < nextval) |
3969 | nextval = thisval; | ||
3952 | } | 3970 | } |
3953 | 3971 | ||
3954 | if (!best) | 3972 | if (!best) |
3955 | return NULL; | 3973 | return NULL; |
3956 | 3974 | ||
3957 | if (size) | 3975 | if (size) |
3958 | *size = nextval - kallsyms->symtab[best].st_value; | 3976 | *size = nextval - bestval; |
3959 | if (offset) | 3977 | if (offset) |
3960 | *offset = addr - kallsyms->symtab[best].st_value; | 3978 | *offset = addr - bestval; |
3961 | return symname(kallsyms, best); | 3979 | |
3980 | return kallsyms_symbol_name(kallsyms, best); | ||
3962 | } | 3981 | } |
3963 | 3982 | ||
3964 | void * __weak dereference_module_function_descriptor(struct module *mod, | 3983 | void * __weak dereference_module_function_descriptor(struct module *mod, |
@@ -3983,7 +4002,8 @@ const char *module_address_lookup(unsigned long addr, | |||
3983 | if (mod) { | 4002 | if (mod) { |
3984 | if (modname) | 4003 | if (modname) |
3985 | *modname = mod->name; | 4004 | *modname = mod->name; |
3986 | ret = get_ksymbol(mod, addr, size, offset); | 4005 | |
4006 | ret = find_kallsyms_symbol(mod, addr, size, offset); | ||
3987 | } | 4007 | } |
3988 | /* Make a copy in here where it's safe */ | 4008 | /* Make a copy in here where it's safe */ |
3989 | if (ret) { | 4009 | if (ret) { |
@@ -4006,9 +4026,10 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
4006 | if (within_module(addr, mod)) { | 4026 | if (within_module(addr, mod)) { |
4007 | const char *sym; | 4027 | const char *sym; |
4008 | 4028 | ||
4009 | sym = get_ksymbol(mod, addr, NULL, NULL); | 4029 | sym = find_kallsyms_symbol(mod, addr, NULL, NULL); |
4010 | if (!sym) | 4030 | if (!sym) |
4011 | goto out; | 4031 | goto out; |
4032 | |||
4012 | strlcpy(symname, sym, KSYM_NAME_LEN); | 4033 | strlcpy(symname, sym, KSYM_NAME_LEN); |
4013 | preempt_enable(); | 4034 | preempt_enable(); |
4014 | return 0; | 4035 | return 0; |
@@ -4031,7 +4052,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
4031 | if (within_module(addr, mod)) { | 4052 | if (within_module(addr, mod)) { |
4032 | const char *sym; | 4053 | const char *sym; |
4033 | 4054 | ||
4034 | sym = get_ksymbol(mod, addr, size, offset); | 4055 | sym = find_kallsyms_symbol(mod, addr, size, offset); |
4035 | if (!sym) | 4056 | if (!sym) |
4036 | goto out; | 4057 | goto out; |
4037 | if (modname) | 4058 | if (modname) |
@@ -4060,9 +4081,11 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
4060 | continue; | 4081 | continue; |
4061 | kallsyms = rcu_dereference_sched(mod->kallsyms); | 4082 | kallsyms = rcu_dereference_sched(mod->kallsyms); |
4062 | if (symnum < kallsyms->num_symtab) { | 4083 | if (symnum < kallsyms->num_symtab) { |
4063 | *value = kallsyms->symtab[symnum].st_value; | 4084 | const Elf_Sym *sym = &kallsyms->symtab[symnum]; |
4064 | *type = kallsyms->symtab[symnum].st_info; | 4085 | |
4065 | strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN); | 4086 | *value = kallsyms_symbol_value(sym); |
4087 | *type = sym->st_size; | ||
4088 | strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN); | ||
4066 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); | 4089 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); |
4067 | *exported = is_exported(name, *value, mod); | 4090 | *exported = is_exported(name, *value, mod); |
4068 | preempt_enable(); | 4091 | preempt_enable(); |
@@ -4074,15 +4097,19 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
4074 | return -ERANGE; | 4097 | return -ERANGE; |
4075 | } | 4098 | } |
4076 | 4099 | ||
4077 | static unsigned long mod_find_symname(struct module *mod, const char *name) | 4100 | /* Given a module and name of symbol, find and return the symbol's value */ |
4101 | static unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name) | ||
4078 | { | 4102 | { |
4079 | unsigned int i; | 4103 | unsigned int i; |
4080 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); | 4104 | struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); |
4081 | 4105 | ||
4082 | for (i = 0; i < kallsyms->num_symtab; i++) | 4106 | for (i = 0; i < kallsyms->num_symtab; i++) { |
4083 | if (strcmp(name, symname(kallsyms, i)) == 0 && | 4107 | const Elf_Sym *sym = &kallsyms->symtab[i]; |
4084 | kallsyms->symtab[i].st_shndx != SHN_UNDEF) | 4108 | |
4085 | return kallsyms->symtab[i].st_value; | 4109 | if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 && |
4110 | sym->st_shndx != SHN_UNDEF) | ||
4111 | return kallsyms_symbol_value(sym); | ||
4112 | } | ||
4086 | return 0; | 4113 | return 0; |
4087 | } | 4114 | } |
4088 | 4115 | ||
@@ -4097,12 +4124,12 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
4097 | preempt_disable(); | 4124 | preempt_disable(); |
4098 | if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { | 4125 | if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { |
4099 | if ((mod = find_module_all(name, colon - name, false)) != NULL) | 4126 | if ((mod = find_module_all(name, colon - name, false)) != NULL) |
4100 | ret = mod_find_symname(mod, colon+1); | 4127 | ret = find_kallsyms_symbol_value(mod, colon+1); |
4101 | } else { | 4128 | } else { |
4102 | list_for_each_entry_rcu(mod, &modules, list) { | 4129 | list_for_each_entry_rcu(mod, &modules, list) { |
4103 | if (mod->state == MODULE_STATE_UNFORMED) | 4130 | if (mod->state == MODULE_STATE_UNFORMED) |
4104 | continue; | 4131 | continue; |
4105 | if ((ret = mod_find_symname(mod, name)) != 0) | 4132 | if ((ret = find_kallsyms_symbol_value(mod, name)) != 0) |
4106 | break; | 4133 | break; |
4107 | } | 4134 | } |
4108 | } | 4135 | } |
@@ -4127,12 +4154,13 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, | |||
4127 | if (mod->state == MODULE_STATE_UNFORMED) | 4154 | if (mod->state == MODULE_STATE_UNFORMED) |
4128 | continue; | 4155 | continue; |
4129 | for (i = 0; i < kallsyms->num_symtab; i++) { | 4156 | for (i = 0; i < kallsyms->num_symtab; i++) { |
4157 | const Elf_Sym *sym = &kallsyms->symtab[i]; | ||
4130 | 4158 | ||
4131 | if (kallsyms->symtab[i].st_shndx == SHN_UNDEF) | 4159 | if (sym->st_shndx == SHN_UNDEF) |
4132 | continue; | 4160 | continue; |
4133 | 4161 | ||
4134 | ret = fn(data, symname(kallsyms, i), | 4162 | ret = fn(data, kallsyms_symbol_name(kallsyms, i), |
4135 | mod, kallsyms->symtab[i].st_value); | 4163 | mod, kallsyms_symbol_value(sym)); |
4136 | if (ret != 0) | 4164 | if (ret != 0) |
4137 | return ret; | 4165 | return ret; |
4138 | } | 4166 | } |