Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Module kallsyms support
0004  *
0005  * Copyright (C) 2010 Rusty Russell
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/kallsyms.h>
0010 #include <linux/buildid.h>
0011 #include <linux/bsearch.h>
0012 #include "internal.h"
0013 
0014 /* Lookup exported symbol in given range of kernel_symbols */
0015 static const struct kernel_symbol *lookup_exported_symbol(const char *name,
0016                               const struct kernel_symbol *start,
0017                               const struct kernel_symbol *stop)
0018 {
0019     return bsearch(name, start, stop - start,
0020             sizeof(struct kernel_symbol), cmp_name);
0021 }
0022 
0023 static int is_exported(const char *name, unsigned long value,
0024                const struct module *mod)
0025 {
0026     const struct kernel_symbol *ks;
0027 
0028     if (!mod)
0029         ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab);
0030     else
0031         ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms);
0032 
0033     return ks && kernel_symbol_value(ks) == value;
0034 }
0035 
0036 /* As per nm */
0037 static char elf_type(const Elf_Sym *sym, const struct load_info *info)
0038 {
0039     const Elf_Shdr *sechdrs = info->sechdrs;
0040 
0041     if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
0042         if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)
0043             return 'v';
0044         else
0045             return 'w';
0046     }
0047     if (sym->st_shndx == SHN_UNDEF)
0048         return 'U';
0049     if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
0050         return 'a';
0051     if (sym->st_shndx >= SHN_LORESERVE)
0052         return '?';
0053     if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR)
0054         return 't';
0055     if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC &&
0056         sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) {
0057         if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE))
0058             return 'r';
0059         else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
0060             return 'g';
0061         else
0062             return 'd';
0063     }
0064     if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {
0065         if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
0066             return 's';
0067         else
0068             return 'b';
0069     }
0070     if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name,
0071               ".debug")) {
0072         return 'n';
0073     }
0074     return '?';
0075 }
0076 
0077 static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
0078                unsigned int shnum, unsigned int pcpundx)
0079 {
0080     const Elf_Shdr *sec;
0081 
0082     if (src->st_shndx == SHN_UNDEF ||
0083         src->st_shndx >= shnum ||
0084         !src->st_name)
0085         return false;
0086 
0087 #ifdef CONFIG_KALLSYMS_ALL
0088     if (src->st_shndx == pcpundx)
0089         return true;
0090 #endif
0091 
0092     sec = sechdrs + src->st_shndx;
0093     if (!(sec->sh_flags & SHF_ALLOC)
0094 #ifndef CONFIG_KALLSYMS_ALL
0095         || !(sec->sh_flags & SHF_EXECINSTR)
0096 #endif
0097         || (sec->sh_entsize & INIT_OFFSET_MASK))
0098         return false;
0099 
0100     return true;
0101 }
0102 
0103 /*
0104  * We only allocate and copy the strings needed by the parts of symtab
0105  * we keep.  This is simple, but has the effect of making multiple
0106  * copies of duplicates.  We could be more sophisticated, see
0107  * linux-kernel thread starting with
0108  * <73defb5e4bca04a6431392cc341112b1@localhost>.
0109  */
0110 void layout_symtab(struct module *mod, struct load_info *info)
0111 {
0112     Elf_Shdr *symsect = info->sechdrs + info->index.sym;
0113     Elf_Shdr *strsect = info->sechdrs + info->index.str;
0114     const Elf_Sym *src;
0115     unsigned int i, nsrc, ndst, strtab_size = 0;
0116 
0117     /* Put symbol section at end of init part of module. */
0118     symsect->sh_flags |= SHF_ALLOC;
0119     symsect->sh_entsize = module_get_offset(mod, &mod->init_layout.size, symsect,
0120                         info->index.sym) | INIT_OFFSET_MASK;
0121     pr_debug("\t%s\n", info->secstrings + symsect->sh_name);
0122 
0123     src = (void *)info->hdr + symsect->sh_offset;
0124     nsrc = symsect->sh_size / sizeof(*src);
0125 
0126     /* Compute total space required for the core symbols' strtab. */
0127     for (ndst = i = 0; i < nsrc; i++) {
0128         if (i == 0 || is_livepatch_module(mod) ||
0129             is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
0130                    info->index.pcpu)) {
0131             strtab_size += strlen(&info->strtab[src[i].st_name]) + 1;
0132             ndst++;
0133         }
0134     }
0135 
0136     /* Append room for core symbols at end of core part. */
0137     info->symoffs = ALIGN(mod->data_layout.size, symsect->sh_addralign ?: 1);
0138     info->stroffs = mod->data_layout.size = info->symoffs + ndst * sizeof(Elf_Sym);
0139     mod->data_layout.size += strtab_size;
0140     /* Note add_kallsyms() computes strtab_size as core_typeoffs - stroffs */
0141     info->core_typeoffs = mod->data_layout.size;
0142     mod->data_layout.size += ndst * sizeof(char);
0143     mod->data_layout.size = strict_align(mod->data_layout.size);
0144 
0145     /* Put string table section at end of init part of module. */
0146     strsect->sh_flags |= SHF_ALLOC;
0147     strsect->sh_entsize = module_get_offset(mod, &mod->init_layout.size, strsect,
0148                         info->index.str) | INIT_OFFSET_MASK;
0149     pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
0150 
0151     /* We'll tack temporary mod_kallsyms on the end. */
0152     mod->init_layout.size = ALIGN(mod->init_layout.size,
0153                       __alignof__(struct mod_kallsyms));
0154     info->mod_kallsyms_init_off = mod->init_layout.size;
0155     mod->init_layout.size += sizeof(struct mod_kallsyms);
0156     info->init_typeoffs = mod->init_layout.size;
0157     mod->init_layout.size += nsrc * sizeof(char);
0158     mod->init_layout.size = strict_align(mod->init_layout.size);
0159 }
0160 
0161 /*
0162  * We use the full symtab and strtab which layout_symtab arranged to
0163  * be appended to the init section.  Later we switch to the cut-down
0164  * core-only ones.
0165  */
0166 void add_kallsyms(struct module *mod, const struct load_info *info)
0167 {
0168     unsigned int i, ndst;
0169     const Elf_Sym *src;
0170     Elf_Sym *dst;
0171     char *s;
0172     Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
0173     unsigned long strtab_size;
0174 
0175     /* Set up to point into init section. */
0176     mod->kallsyms = (void __rcu *)mod->init_layout.base +
0177         info->mod_kallsyms_init_off;
0178 
0179     rcu_read_lock();
0180     /* The following is safe since this pointer cannot change */
0181     rcu_dereference(mod->kallsyms)->symtab = (void *)symsec->sh_addr;
0182     rcu_dereference(mod->kallsyms)->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
0183     /* Make sure we get permanent strtab: don't use info->strtab. */
0184     rcu_dereference(mod->kallsyms)->strtab =
0185         (void *)info->sechdrs[info->index.str].sh_addr;
0186     rcu_dereference(mod->kallsyms)->typetab = mod->init_layout.base + info->init_typeoffs;
0187 
0188     /*
0189      * Now populate the cut down core kallsyms for after init
0190      * and set types up while we still have access to sections.
0191      */
0192     mod->core_kallsyms.symtab = dst = mod->data_layout.base + info->symoffs;
0193     mod->core_kallsyms.strtab = s = mod->data_layout.base + info->stroffs;
0194     mod->core_kallsyms.typetab = mod->data_layout.base + info->core_typeoffs;
0195     strtab_size = info->core_typeoffs - info->stroffs;
0196     src = rcu_dereference(mod->kallsyms)->symtab;
0197     for (ndst = i = 0; i < rcu_dereference(mod->kallsyms)->num_symtab; i++) {
0198         rcu_dereference(mod->kallsyms)->typetab[i] = elf_type(src + i, info);
0199         if (i == 0 || is_livepatch_module(mod) ||
0200             is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
0201                    info->index.pcpu)) {
0202             ssize_t ret;
0203 
0204             mod->core_kallsyms.typetab[ndst] =
0205                 rcu_dereference(mod->kallsyms)->typetab[i];
0206             dst[ndst] = src[i];
0207             dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
0208             ret = strscpy(s,
0209                       &rcu_dereference(mod->kallsyms)->strtab[src[i].st_name],
0210                       strtab_size);
0211             if (ret < 0)
0212                 break;
0213             s += ret + 1;
0214             strtab_size -= ret + 1;
0215         }
0216     }
0217     rcu_read_unlock();
0218     mod->core_kallsyms.num_symtab = ndst;
0219 }
0220 
0221 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
0222 void init_build_id(struct module *mod, const struct load_info *info)
0223 {
0224     const Elf_Shdr *sechdr;
0225     unsigned int i;
0226 
0227     for (i = 0; i < info->hdr->e_shnum; i++) {
0228         sechdr = &info->sechdrs[i];
0229         if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE &&
0230             !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id,
0231                     sechdr->sh_size))
0232             break;
0233     }
0234 }
0235 #else
0236 void init_build_id(struct module *mod, const struct load_info *info)
0237 {
0238 }
0239 #endif
0240 
0241 /*
0242  * This ignores the intensely annoying "mapping symbols" found
0243  * in ARM ELF files: $a, $t and $d.
0244  */
0245 static inline int is_arm_mapping_symbol(const char *str)
0246 {
0247     if (str[0] == '.' && str[1] == 'L')
0248         return true;
0249     return str[0] == '$' && strchr("axtd", str[1]) &&
0250            (str[2] == '\0' || str[2] == '.');
0251 }
0252 
0253 static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum)
0254 {
0255     return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
0256 }
0257 
0258 /*
0259  * Given a module and address, find the corresponding symbol and return its name
0260  * while providing its size and offset if needed.
0261  */
0262 static const char *find_kallsyms_symbol(struct module *mod,
0263                     unsigned long addr,
0264                     unsigned long *size,
0265                     unsigned long *offset)
0266 {
0267     unsigned int i, best = 0;
0268     unsigned long nextval, bestval;
0269     struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
0270 
0271     /* At worse, next value is at end of module */
0272     if (within_module_init(addr, mod))
0273         nextval = (unsigned long)mod->init_layout.base + mod->init_layout.text_size;
0274     else
0275         nextval = (unsigned long)mod->core_layout.base + mod->core_layout.text_size;
0276 
0277     bestval = kallsyms_symbol_value(&kallsyms->symtab[best]);
0278 
0279     /*
0280      * Scan for closest preceding symbol, and next symbol. (ELF
0281      * starts real symbols at 1).
0282      */
0283     for (i = 1; i < kallsyms->num_symtab; i++) {
0284         const Elf_Sym *sym = &kallsyms->symtab[i];
0285         unsigned long thisval = kallsyms_symbol_value(sym);
0286 
0287         if (sym->st_shndx == SHN_UNDEF)
0288             continue;
0289 
0290         /*
0291          * We ignore unnamed symbols: they're uninformative
0292          * and inserted at a whim.
0293          */
0294         if (*kallsyms_symbol_name(kallsyms, i) == '\0' ||
0295             is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i)))
0296             continue;
0297 
0298         if (thisval <= addr && thisval > bestval) {
0299             best = i;
0300             bestval = thisval;
0301         }
0302         if (thisval > addr && thisval < nextval)
0303             nextval = thisval;
0304     }
0305 
0306     if (!best)
0307         return NULL;
0308 
0309     if (size)
0310         *size = nextval - bestval;
0311     if (offset)
0312         *offset = addr - bestval;
0313 
0314     return kallsyms_symbol_name(kallsyms, best);
0315 }
0316 
0317 void * __weak dereference_module_function_descriptor(struct module *mod,
0318                              void *ptr)
0319 {
0320     return ptr;
0321 }
0322 
0323 /*
0324  * For kallsyms to ask for address resolution.  NULL means not found.  Careful
0325  * not to lock to avoid deadlock on oopses, simply disable preemption.
0326  */
0327 const char *module_address_lookup(unsigned long addr,
0328                   unsigned long *size,
0329                 unsigned long *offset,
0330                 char **modname,
0331                 const unsigned char **modbuildid,
0332                 char *namebuf)
0333 {
0334     const char *ret = NULL;
0335     struct module *mod;
0336 
0337     preempt_disable();
0338     mod = __module_address(addr);
0339     if (mod) {
0340         if (modname)
0341             *modname = mod->name;
0342         if (modbuildid) {
0343 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
0344             *modbuildid = mod->build_id;
0345 #else
0346             *modbuildid = NULL;
0347 #endif
0348         }
0349 
0350         ret = find_kallsyms_symbol(mod, addr, size, offset);
0351     }
0352     /* Make a copy in here where it's safe */
0353     if (ret) {
0354         strncpy(namebuf, ret, KSYM_NAME_LEN - 1);
0355         ret = namebuf;
0356     }
0357     preempt_enable();
0358 
0359     return ret;
0360 }
0361 
0362 int lookup_module_symbol_name(unsigned long addr, char *symname)
0363 {
0364     struct module *mod;
0365 
0366     preempt_disable();
0367     list_for_each_entry_rcu(mod, &modules, list) {
0368         if (mod->state == MODULE_STATE_UNFORMED)
0369             continue;
0370         if (within_module(addr, mod)) {
0371             const char *sym;
0372 
0373             sym = find_kallsyms_symbol(mod, addr, NULL, NULL);
0374             if (!sym)
0375                 goto out;
0376 
0377             strscpy(symname, sym, KSYM_NAME_LEN);
0378             preempt_enable();
0379             return 0;
0380         }
0381     }
0382 out:
0383     preempt_enable();
0384     return -ERANGE;
0385 }
0386 
0387 int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
0388                    unsigned long *offset, char *modname, char *name)
0389 {
0390     struct module *mod;
0391 
0392     preempt_disable();
0393     list_for_each_entry_rcu(mod, &modules, list) {
0394         if (mod->state == MODULE_STATE_UNFORMED)
0395             continue;
0396         if (within_module(addr, mod)) {
0397             const char *sym;
0398 
0399             sym = find_kallsyms_symbol(mod, addr, size, offset);
0400             if (!sym)
0401                 goto out;
0402             if (modname)
0403                 strscpy(modname, mod->name, MODULE_NAME_LEN);
0404             if (name)
0405                 strscpy(name, sym, KSYM_NAME_LEN);
0406             preempt_enable();
0407             return 0;
0408         }
0409     }
0410 out:
0411     preempt_enable();
0412     return -ERANGE;
0413 }
0414 
0415 int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
0416                char *name, char *module_name, int *exported)
0417 {
0418     struct module *mod;
0419 
0420     preempt_disable();
0421     list_for_each_entry_rcu(mod, &modules, list) {
0422         struct mod_kallsyms *kallsyms;
0423 
0424         if (mod->state == MODULE_STATE_UNFORMED)
0425             continue;
0426         kallsyms = rcu_dereference_sched(mod->kallsyms);
0427         if (symnum < kallsyms->num_symtab) {
0428             const Elf_Sym *sym = &kallsyms->symtab[symnum];
0429 
0430             *value = kallsyms_symbol_value(sym);
0431             *type = kallsyms->typetab[symnum];
0432             strscpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
0433             strscpy(module_name, mod->name, MODULE_NAME_LEN);
0434             *exported = is_exported(name, *value, mod);
0435             preempt_enable();
0436             return 0;
0437         }
0438         symnum -= kallsyms->num_symtab;
0439     }
0440     preempt_enable();
0441     return -ERANGE;
0442 }
0443 
0444 /* Given a module and name of symbol, find and return the symbol's value */
0445 unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name)
0446 {
0447     unsigned int i;
0448     struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
0449 
0450     for (i = 0; i < kallsyms->num_symtab; i++) {
0451         const Elf_Sym *sym = &kallsyms->symtab[i];
0452 
0453         if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 &&
0454             sym->st_shndx != SHN_UNDEF)
0455             return kallsyms_symbol_value(sym);
0456     }
0457     return 0;
0458 }
0459 
0460 static unsigned long __module_kallsyms_lookup_name(const char *name)
0461 {
0462     struct module *mod;
0463     char *colon;
0464 
0465     colon = strnchr(name, MODULE_NAME_LEN, ':');
0466     if (colon) {
0467         mod = find_module_all(name, colon - name, false);
0468         if (mod)
0469             return find_kallsyms_symbol_value(mod, colon + 1);
0470         return 0;
0471     }
0472 
0473     list_for_each_entry_rcu(mod, &modules, list) {
0474         unsigned long ret;
0475 
0476         if (mod->state == MODULE_STATE_UNFORMED)
0477             continue;
0478         ret = find_kallsyms_symbol_value(mod, name);
0479         if (ret)
0480             return ret;
0481     }
0482     return 0;
0483 }
0484 
0485 /* Look for this name: can be of form module:name. */
0486 unsigned long module_kallsyms_lookup_name(const char *name)
0487 {
0488     unsigned long ret;
0489 
0490     /* Don't lock: we're in enough trouble already. */
0491     preempt_disable();
0492     ret = __module_kallsyms_lookup_name(name);
0493     preempt_enable();
0494     return ret;
0495 }
0496 
0497 #ifdef CONFIG_LIVEPATCH
0498 int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
0499                          struct module *, unsigned long),
0500                    void *data)
0501 {
0502     struct module *mod;
0503     unsigned int i;
0504     int ret = 0;
0505 
0506     mutex_lock(&module_mutex);
0507     list_for_each_entry(mod, &modules, list) {
0508         struct mod_kallsyms *kallsyms;
0509 
0510         if (mod->state == MODULE_STATE_UNFORMED)
0511             continue;
0512 
0513         /* Use rcu_dereference_sched() to remain compliant with the sparse tool */
0514         preempt_disable();
0515         kallsyms = rcu_dereference_sched(mod->kallsyms);
0516         preempt_enable();
0517 
0518         for (i = 0; i < kallsyms->num_symtab; i++) {
0519             const Elf_Sym *sym = &kallsyms->symtab[i];
0520 
0521             if (sym->st_shndx == SHN_UNDEF)
0522                 continue;
0523 
0524             ret = fn(data, kallsyms_symbol_name(kallsyms, i),
0525                  mod, kallsyms_symbol_value(sym));
0526             if (ret != 0)
0527                 goto out;
0528         }
0529     }
0530 out:
0531     mutex_unlock(&module_mutex);
0532     return ret;
0533 }
0534 #endif /* CONFIG_LIVEPATCH */