Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
0004  *
0005  * Rewritten and vastly simplified by Rusty Russell for in-kernel
0006  * module loader:
0007  *   Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
0008  *
0009  * ChangeLog:
0010  *
0011  * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
0012  *      Changed the compression method from stem compression to "table lookup"
0013  *      compression (see scripts/kallsyms.c for a more complete description)
0014  */
0015 #include <linux/kallsyms.h>
0016 #include <linux/init.h>
0017 #include <linux/seq_file.h>
0018 #include <linux/fs.h>
0019 #include <linux/kdb.h>
0020 #include <linux/err.h>
0021 #include <linux/proc_fs.h>
0022 #include <linux/sched.h>    /* for cond_resched */
0023 #include <linux/ctype.h>
0024 #include <linux/slab.h>
0025 #include <linux/filter.h>
0026 #include <linux/ftrace.h>
0027 #include <linux/kprobes.h>
0028 #include <linux/build_bug.h>
0029 #include <linux/compiler.h>
0030 #include <linux/module.h>
0031 #include <linux/kernel.h>
0032 #include <linux/bsearch.h>
0033 #include <linux/btf_ids.h>
0034 
0035 #include "kallsyms_internal.h"
0036 
0037 /*
0038  * Expand a compressed symbol data into the resulting uncompressed string,
0039  * if uncompressed string is too long (>= maxlen), it will be truncated,
0040  * given the offset to where the symbol is in the compressed stream.
0041  */
0042 static unsigned int kallsyms_expand_symbol(unsigned int off,
0043                        char *result, size_t maxlen)
0044 {
0045     int len, skipped_first = 0;
0046     const char *tptr;
0047     const u8 *data;
0048 
0049     /* Get the compressed symbol length from the first symbol byte. */
0050     data = &kallsyms_names[off];
0051     len = *data;
0052     data++;
0053 
0054     /*
0055      * Update the offset to return the offset for the next symbol on
0056      * the compressed stream.
0057      */
0058     off += len + 1;
0059 
0060     /*
0061      * For every byte on the compressed symbol data, copy the table
0062      * entry for that byte.
0063      */
0064     while (len) {
0065         tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
0066         data++;
0067         len--;
0068 
0069         while (*tptr) {
0070             if (skipped_first) {
0071                 if (maxlen <= 1)
0072                     goto tail;
0073                 *result = *tptr;
0074                 result++;
0075                 maxlen--;
0076             } else
0077                 skipped_first = 1;
0078             tptr++;
0079         }
0080     }
0081 
0082 tail:
0083     if (maxlen)
0084         *result = '\0';
0085 
0086     /* Return to offset to the next symbol. */
0087     return off;
0088 }
0089 
0090 /*
0091  * Get symbol type information. This is encoded as a single char at the
0092  * beginning of the symbol name.
0093  */
0094 static char kallsyms_get_symbol_type(unsigned int off)
0095 {
0096     /*
0097      * Get just the first code, look it up in the token table,
0098      * and return the first char from this token.
0099      */
0100     return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
0101 }
0102 
0103 
0104 /*
0105  * Find the offset on the compressed stream given and index in the
0106  * kallsyms array.
0107  */
0108 static unsigned int get_symbol_offset(unsigned long pos)
0109 {
0110     const u8 *name;
0111     int i;
0112 
0113     /*
0114      * Use the closest marker we have. We have markers every 256 positions,
0115      * so that should be close enough.
0116      */
0117     name = &kallsyms_names[kallsyms_markers[pos >> 8]];
0118 
0119     /*
0120      * Sequentially scan all the symbols up to the point we're searching
0121      * for. Every symbol is stored in a [<len>][<len> bytes of data] format,
0122      * so we just need to add the len to the current pointer for every
0123      * symbol we wish to skip.
0124      */
0125     for (i = 0; i < (pos & 0xFF); i++)
0126         name = name + (*name) + 1;
0127 
0128     return name - kallsyms_names;
0129 }
0130 
0131 static unsigned long kallsyms_sym_address(int idx)
0132 {
0133     if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
0134         return kallsyms_addresses[idx];
0135 
0136     /* values are unsigned offsets if --absolute-percpu is not in effect */
0137     if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
0138         return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
0139 
0140     /* ...otherwise, positive offsets are absolute values */
0141     if (kallsyms_offsets[idx] >= 0)
0142         return kallsyms_offsets[idx];
0143 
0144     /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
0145     return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
0146 }
0147 
0148 static bool cleanup_symbol_name(char *s)
0149 {
0150     char *res;
0151 
0152     if (!IS_ENABLED(CONFIG_LTO_CLANG))
0153         return false;
0154 
0155     /*
0156      * LLVM appends various suffixes for local functions and variables that
0157      * must be promoted to global scope as part of LTO.  This can break
0158      * hooking of static functions with kprobes. '.' is not a valid
0159      * character in an identifier in C. Suffixes observed:
0160      * - foo.llvm.[0-9a-f]+
0161      * - foo.[0-9a-f]+
0162      * - foo.[0-9a-f]+.cfi_jt
0163      */
0164     res = strchr(s, '.');
0165     if (res) {
0166         *res = '\0';
0167         return true;
0168     }
0169 
0170     if (!IS_ENABLED(CONFIG_CFI_CLANG) ||
0171         !IS_ENABLED(CONFIG_LTO_CLANG_THIN) ||
0172         CONFIG_CLANG_VERSION >= 130000)
0173         return false;
0174 
0175     /*
0176      * Prior to LLVM 13, the following suffixes were observed when thinLTO
0177      * and CFI are both enabled:
0178      * - foo$[0-9]+
0179      */
0180     res = strrchr(s, '$');
0181     if (res) {
0182         *res = '\0';
0183         return true;
0184     }
0185 
0186     return false;
0187 }
0188 
0189 /* Lookup the address for this symbol. Returns 0 if not found. */
0190 unsigned long kallsyms_lookup_name(const char *name)
0191 {
0192     char namebuf[KSYM_NAME_LEN];
0193     unsigned long i;
0194     unsigned int off;
0195 
0196     /* Skip the search for empty string. */
0197     if (!*name)
0198         return 0;
0199 
0200     for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
0201         off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
0202 
0203         if (strcmp(namebuf, name) == 0)
0204             return kallsyms_sym_address(i);
0205 
0206         if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0)
0207             return kallsyms_sym_address(i);
0208     }
0209     return module_kallsyms_lookup_name(name);
0210 }
0211 
0212 /*
0213  * Iterate over all symbols in vmlinux.  For symbols from modules use
0214  * module_kallsyms_on_each_symbol instead.
0215  */
0216 int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
0217                       unsigned long),
0218                 void *data)
0219 {
0220     char namebuf[KSYM_NAME_LEN];
0221     unsigned long i;
0222     unsigned int off;
0223     int ret;
0224 
0225     for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
0226         off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
0227         ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
0228         if (ret != 0)
0229             return ret;
0230         cond_resched();
0231     }
0232     return 0;
0233 }
0234 
0235 static unsigned long get_symbol_pos(unsigned long addr,
0236                     unsigned long *symbolsize,
0237                     unsigned long *offset)
0238 {
0239     unsigned long symbol_start = 0, symbol_end = 0;
0240     unsigned long i, low, high, mid;
0241 
0242     /* This kernel should never had been booted. */
0243     if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
0244         BUG_ON(!kallsyms_addresses);
0245     else
0246         BUG_ON(!kallsyms_offsets);
0247 
0248     /* Do a binary search on the sorted kallsyms_addresses array. */
0249     low = 0;
0250     high = kallsyms_num_syms;
0251 
0252     while (high - low > 1) {
0253         mid = low + (high - low) / 2;
0254         if (kallsyms_sym_address(mid) <= addr)
0255             low = mid;
0256         else
0257             high = mid;
0258     }
0259 
0260     /*
0261      * Search for the first aliased symbol. Aliased
0262      * symbols are symbols with the same address.
0263      */
0264     while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
0265         --low;
0266 
0267     symbol_start = kallsyms_sym_address(low);
0268 
0269     /* Search for next non-aliased symbol. */
0270     for (i = low + 1; i < kallsyms_num_syms; i++) {
0271         if (kallsyms_sym_address(i) > symbol_start) {
0272             symbol_end = kallsyms_sym_address(i);
0273             break;
0274         }
0275     }
0276 
0277     /* If we found no next symbol, we use the end of the section. */
0278     if (!symbol_end) {
0279         if (is_kernel_inittext(addr))
0280             symbol_end = (unsigned long)_einittext;
0281         else if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
0282             symbol_end = (unsigned long)_end;
0283         else
0284             symbol_end = (unsigned long)_etext;
0285     }
0286 
0287     if (symbolsize)
0288         *symbolsize = symbol_end - symbol_start;
0289     if (offset)
0290         *offset = addr - symbol_start;
0291 
0292     return low;
0293 }
0294 
0295 /*
0296  * Lookup an address but don't bother to find any names.
0297  */
0298 int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
0299                 unsigned long *offset)
0300 {
0301     char namebuf[KSYM_NAME_LEN];
0302 
0303     if (is_ksym_addr(addr)) {
0304         get_symbol_pos(addr, symbolsize, offset);
0305         return 1;
0306     }
0307     return !!module_address_lookup(addr, symbolsize, offset, NULL, NULL, namebuf) ||
0308            !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
0309 }
0310 
0311 static const char *kallsyms_lookup_buildid(unsigned long addr,
0312             unsigned long *symbolsize,
0313             unsigned long *offset, char **modname,
0314             const unsigned char **modbuildid, char *namebuf)
0315 {
0316     const char *ret;
0317 
0318     namebuf[KSYM_NAME_LEN - 1] = 0;
0319     namebuf[0] = 0;
0320 
0321     if (is_ksym_addr(addr)) {
0322         unsigned long pos;
0323 
0324         pos = get_symbol_pos(addr, symbolsize, offset);
0325         /* Grab name */
0326         kallsyms_expand_symbol(get_symbol_offset(pos),
0327                        namebuf, KSYM_NAME_LEN);
0328         if (modname)
0329             *modname = NULL;
0330         if (modbuildid)
0331             *modbuildid = NULL;
0332 
0333         ret = namebuf;
0334         goto found;
0335     }
0336 
0337     /* See if it's in a module or a BPF JITed image. */
0338     ret = module_address_lookup(addr, symbolsize, offset,
0339                     modname, modbuildid, namebuf);
0340     if (!ret)
0341         ret = bpf_address_lookup(addr, symbolsize,
0342                      offset, modname, namebuf);
0343 
0344     if (!ret)
0345         ret = ftrace_mod_address_lookup(addr, symbolsize,
0346                         offset, modname, namebuf);
0347 
0348 found:
0349     cleanup_symbol_name(namebuf);
0350     return ret;
0351 }
0352 
0353 /*
0354  * Lookup an address
0355  * - modname is set to NULL if it's in the kernel.
0356  * - We guarantee that the returned name is valid until we reschedule even if.
0357  *   It resides in a module.
0358  * - We also guarantee that modname will be valid until rescheduled.
0359  */
0360 const char *kallsyms_lookup(unsigned long addr,
0361                 unsigned long *symbolsize,
0362                 unsigned long *offset,
0363                 char **modname, char *namebuf)
0364 {
0365     return kallsyms_lookup_buildid(addr, symbolsize, offset, modname,
0366                        NULL, namebuf);
0367 }
0368 
0369 int lookup_symbol_name(unsigned long addr, char *symname)
0370 {
0371     int res;
0372 
0373     symname[0] = '\0';
0374     symname[KSYM_NAME_LEN - 1] = '\0';
0375 
0376     if (is_ksym_addr(addr)) {
0377         unsigned long pos;
0378 
0379         pos = get_symbol_pos(addr, NULL, NULL);
0380         /* Grab name */
0381         kallsyms_expand_symbol(get_symbol_offset(pos),
0382                        symname, KSYM_NAME_LEN);
0383         goto found;
0384     }
0385     /* See if it's in a module. */
0386     res = lookup_module_symbol_name(addr, symname);
0387     if (res)
0388         return res;
0389 
0390 found:
0391     cleanup_symbol_name(symname);
0392     return 0;
0393 }
0394 
0395 int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
0396             unsigned long *offset, char *modname, char *name)
0397 {
0398     int res;
0399 
0400     name[0] = '\0';
0401     name[KSYM_NAME_LEN - 1] = '\0';
0402 
0403     if (is_ksym_addr(addr)) {
0404         unsigned long pos;
0405 
0406         pos = get_symbol_pos(addr, size, offset);
0407         /* Grab name */
0408         kallsyms_expand_symbol(get_symbol_offset(pos),
0409                        name, KSYM_NAME_LEN);
0410         modname[0] = '\0';
0411         goto found;
0412     }
0413     /* See if it's in a module. */
0414     res = lookup_module_symbol_attrs(addr, size, offset, modname, name);
0415     if (res)
0416         return res;
0417 
0418 found:
0419     cleanup_symbol_name(name);
0420     return 0;
0421 }
0422 
0423 /* Look up a kernel symbol and return it in a text buffer. */
0424 static int __sprint_symbol(char *buffer, unsigned long address,
0425                int symbol_offset, int add_offset, int add_buildid)
0426 {
0427     char *modname;
0428     const unsigned char *buildid;
0429     const char *name;
0430     unsigned long offset, size;
0431     int len;
0432 
0433     address += symbol_offset;
0434     name = kallsyms_lookup_buildid(address, &size, &offset, &modname, &buildid,
0435                        buffer);
0436     if (!name)
0437         return sprintf(buffer, "0x%lx", address - symbol_offset);
0438 
0439     if (name != buffer)
0440         strcpy(buffer, name);
0441     len = strlen(buffer);
0442     offset -= symbol_offset;
0443 
0444     if (add_offset)
0445         len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
0446 
0447     if (modname) {
0448         len += sprintf(buffer + len, " [%s", modname);
0449 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
0450         if (add_buildid && buildid) {
0451             /* build ID should match length of sprintf */
0452 #if IS_ENABLED(CONFIG_MODULES)
0453             static_assert(sizeof(typeof_member(struct module, build_id)) == 20);
0454 #endif
0455             len += sprintf(buffer + len, " %20phN", buildid);
0456         }
0457 #endif
0458         len += sprintf(buffer + len, "]");
0459     }
0460 
0461     return len;
0462 }
0463 
0464 /**
0465  * sprint_symbol - Look up a kernel symbol and return it in a text buffer
0466  * @buffer: buffer to be stored
0467  * @address: address to lookup
0468  *
0469  * This function looks up a kernel symbol with @address and stores its name,
0470  * offset, size and module name to @buffer if possible. If no symbol was found,
0471  * just saves its @address as is.
0472  *
0473  * This function returns the number of bytes stored in @buffer.
0474  */
0475 int sprint_symbol(char *buffer, unsigned long address)
0476 {
0477     return __sprint_symbol(buffer, address, 0, 1, 0);
0478 }
0479 EXPORT_SYMBOL_GPL(sprint_symbol);
0480 
0481 /**
0482  * sprint_symbol_build_id - Look up a kernel symbol and return it in a text buffer
0483  * @buffer: buffer to be stored
0484  * @address: address to lookup
0485  *
0486  * This function looks up a kernel symbol with @address and stores its name,
0487  * offset, size, module name and module build ID to @buffer if possible. If no
0488  * symbol was found, just saves its @address as is.
0489  *
0490  * This function returns the number of bytes stored in @buffer.
0491  */
0492 int sprint_symbol_build_id(char *buffer, unsigned long address)
0493 {
0494     return __sprint_symbol(buffer, address, 0, 1, 1);
0495 }
0496 EXPORT_SYMBOL_GPL(sprint_symbol_build_id);
0497 
0498 /**
0499  * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
0500  * @buffer: buffer to be stored
0501  * @address: address to lookup
0502  *
0503  * This function looks up a kernel symbol with @address and stores its name
0504  * and module name to @buffer if possible. If no symbol was found, just saves
0505  * its @address as is.
0506  *
0507  * This function returns the number of bytes stored in @buffer.
0508  */
0509 int sprint_symbol_no_offset(char *buffer, unsigned long address)
0510 {
0511     return __sprint_symbol(buffer, address, 0, 0, 0);
0512 }
0513 EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
0514 
0515 /**
0516  * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
0517  * @buffer: buffer to be stored
0518  * @address: address to lookup
0519  *
0520  * This function is for stack backtrace and does the same thing as
0521  * sprint_symbol() but with modified/decreased @address. If there is a
0522  * tail-call to the function marked "noreturn", gcc optimized out code after
0523  * the call so that the stack-saved return address could point outside of the
0524  * caller. This function ensures that kallsyms will find the original caller
0525  * by decreasing @address.
0526  *
0527  * This function returns the number of bytes stored in @buffer.
0528  */
0529 int sprint_backtrace(char *buffer, unsigned long address)
0530 {
0531     return __sprint_symbol(buffer, address, -1, 1, 0);
0532 }
0533 
0534 /**
0535  * sprint_backtrace_build_id - Look up a backtrace symbol and return it in a text buffer
0536  * @buffer: buffer to be stored
0537  * @address: address to lookup
0538  *
0539  * This function is for stack backtrace and does the same thing as
0540  * sprint_symbol() but with modified/decreased @address. If there is a
0541  * tail-call to the function marked "noreturn", gcc optimized out code after
0542  * the call so that the stack-saved return address could point outside of the
0543  * caller. This function ensures that kallsyms will find the original caller
0544  * by decreasing @address. This function also appends the module build ID to
0545  * the @buffer if @address is within a kernel module.
0546  *
0547  * This function returns the number of bytes stored in @buffer.
0548  */
0549 int sprint_backtrace_build_id(char *buffer, unsigned long address)
0550 {
0551     return __sprint_symbol(buffer, address, -1, 1, 1);
0552 }
0553 
0554 /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
0555 struct kallsym_iter {
0556     loff_t pos;
0557     loff_t pos_arch_end;
0558     loff_t pos_mod_end;
0559     loff_t pos_ftrace_mod_end;
0560     loff_t pos_bpf_end;
0561     unsigned long value;
0562     unsigned int nameoff; /* If iterating in core kernel symbols. */
0563     char type;
0564     char name[KSYM_NAME_LEN];
0565     char module_name[MODULE_NAME_LEN];
0566     int exported;
0567     int show_value;
0568 };
0569 
0570 int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
0571                 char *type, char *name)
0572 {
0573     return -EINVAL;
0574 }
0575 
0576 static int get_ksymbol_arch(struct kallsym_iter *iter)
0577 {
0578     int ret = arch_get_kallsym(iter->pos - kallsyms_num_syms,
0579                    &iter->value, &iter->type,
0580                    iter->name);
0581 
0582     if (ret < 0) {
0583         iter->pos_arch_end = iter->pos;
0584         return 0;
0585     }
0586 
0587     return 1;
0588 }
0589 
0590 static int get_ksymbol_mod(struct kallsym_iter *iter)
0591 {
0592     int ret = module_get_kallsym(iter->pos - iter->pos_arch_end,
0593                      &iter->value, &iter->type,
0594                      iter->name, iter->module_name,
0595                      &iter->exported);
0596     if (ret < 0) {
0597         iter->pos_mod_end = iter->pos;
0598         return 0;
0599     }
0600 
0601     return 1;
0602 }
0603 
0604 /*
0605  * ftrace_mod_get_kallsym() may also get symbols for pages allocated for ftrace
0606  * purposes. In that case "__builtin__ftrace" is used as a module name, even
0607  * though "__builtin__ftrace" is not a module.
0608  */
0609 static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter)
0610 {
0611     int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end,
0612                      &iter->value, &iter->type,
0613                      iter->name, iter->module_name,
0614                      &iter->exported);
0615     if (ret < 0) {
0616         iter->pos_ftrace_mod_end = iter->pos;
0617         return 0;
0618     }
0619 
0620     return 1;
0621 }
0622 
0623 static int get_ksymbol_bpf(struct kallsym_iter *iter)
0624 {
0625     int ret;
0626 
0627     strlcpy(iter->module_name, "bpf", MODULE_NAME_LEN);
0628     iter->exported = 0;
0629     ret = bpf_get_kallsym(iter->pos - iter->pos_ftrace_mod_end,
0630                   &iter->value, &iter->type,
0631                   iter->name);
0632     if (ret < 0) {
0633         iter->pos_bpf_end = iter->pos;
0634         return 0;
0635     }
0636 
0637     return 1;
0638 }
0639 
0640 /*
0641  * This uses "__builtin__kprobes" as a module name for symbols for pages
0642  * allocated for kprobes' purposes, even though "__builtin__kprobes" is not a
0643  * module.
0644  */
0645 static int get_ksymbol_kprobe(struct kallsym_iter *iter)
0646 {
0647     strlcpy(iter->module_name, "__builtin__kprobes", MODULE_NAME_LEN);
0648     iter->exported = 0;
0649     return kprobe_get_kallsym(iter->pos - iter->pos_bpf_end,
0650                   &iter->value, &iter->type,
0651                   iter->name) < 0 ? 0 : 1;
0652 }
0653 
0654 /* Returns space to next name. */
0655 static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
0656 {
0657     unsigned off = iter->nameoff;
0658 
0659     iter->module_name[0] = '\0';
0660     iter->value = kallsyms_sym_address(iter->pos);
0661 
0662     iter->type = kallsyms_get_symbol_type(off);
0663 
0664     off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
0665 
0666     return off - iter->nameoff;
0667 }
0668 
0669 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
0670 {
0671     iter->name[0] = '\0';
0672     iter->nameoff = get_symbol_offset(new_pos);
0673     iter->pos = new_pos;
0674     if (new_pos == 0) {
0675         iter->pos_arch_end = 0;
0676         iter->pos_mod_end = 0;
0677         iter->pos_ftrace_mod_end = 0;
0678         iter->pos_bpf_end = 0;
0679     }
0680 }
0681 
0682 /*
0683  * The end position (last + 1) of each additional kallsyms section is recorded
0684  * in iter->pos_..._end as each section is added, and so can be used to
0685  * determine which get_ksymbol_...() function to call next.
0686  */
0687 static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
0688 {
0689     iter->pos = pos;
0690 
0691     if ((!iter->pos_arch_end || iter->pos_arch_end > pos) &&
0692         get_ksymbol_arch(iter))
0693         return 1;
0694 
0695     if ((!iter->pos_mod_end || iter->pos_mod_end > pos) &&
0696         get_ksymbol_mod(iter))
0697         return 1;
0698 
0699     if ((!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > pos) &&
0700         get_ksymbol_ftrace_mod(iter))
0701         return 1;
0702 
0703     if ((!iter->pos_bpf_end || iter->pos_bpf_end > pos) &&
0704         get_ksymbol_bpf(iter))
0705         return 1;
0706 
0707     return get_ksymbol_kprobe(iter);
0708 }
0709 
0710 /* Returns false if pos at or past end of file. */
0711 static int update_iter(struct kallsym_iter *iter, loff_t pos)
0712 {
0713     /* Module symbols can be accessed randomly. */
0714     if (pos >= kallsyms_num_syms)
0715         return update_iter_mod(iter, pos);
0716 
0717     /* If we're not on the desired position, reset to new position. */
0718     if (pos != iter->pos)
0719         reset_iter(iter, pos);
0720 
0721     iter->nameoff += get_ksymbol_core(iter);
0722     iter->pos++;
0723 
0724     return 1;
0725 }
0726 
0727 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
0728 {
0729     (*pos)++;
0730 
0731     if (!update_iter(m->private, *pos))
0732         return NULL;
0733     return p;
0734 }
0735 
0736 static void *s_start(struct seq_file *m, loff_t *pos)
0737 {
0738     if (!update_iter(m->private, *pos))
0739         return NULL;
0740     return m->private;
0741 }
0742 
0743 static void s_stop(struct seq_file *m, void *p)
0744 {
0745 }
0746 
0747 static int s_show(struct seq_file *m, void *p)
0748 {
0749     void *value;
0750     struct kallsym_iter *iter = m->private;
0751 
0752     /* Some debugging symbols have no name.  Ignore them. */
0753     if (!iter->name[0])
0754         return 0;
0755 
0756     value = iter->show_value ? (void *)iter->value : NULL;
0757 
0758     if (iter->module_name[0]) {
0759         char type;
0760 
0761         /*
0762          * Label it "global" if it is exported,
0763          * "local" if not exported.
0764          */
0765         type = iter->exported ? toupper(iter->type) :
0766                     tolower(iter->type);
0767         seq_printf(m, "%px %c %s\t[%s]\n", value,
0768                type, iter->name, iter->module_name);
0769     } else
0770         seq_printf(m, "%px %c %s\n", value,
0771                iter->type, iter->name);
0772     return 0;
0773 }
0774 
0775 static const struct seq_operations kallsyms_op = {
0776     .start = s_start,
0777     .next = s_next,
0778     .stop = s_stop,
0779     .show = s_show
0780 };
0781 
0782 #ifdef CONFIG_BPF_SYSCALL
0783 
0784 struct bpf_iter__ksym {
0785     __bpf_md_ptr(struct bpf_iter_meta *, meta);
0786     __bpf_md_ptr(struct kallsym_iter *, ksym);
0787 };
0788 
0789 static int ksym_prog_seq_show(struct seq_file *m, bool in_stop)
0790 {
0791     struct bpf_iter__ksym ctx;
0792     struct bpf_iter_meta meta;
0793     struct bpf_prog *prog;
0794 
0795     meta.seq = m;
0796     prog = bpf_iter_get_info(&meta, in_stop);
0797     if (!prog)
0798         return 0;
0799 
0800     ctx.meta = &meta;
0801     ctx.ksym = m ? m->private : NULL;
0802     return bpf_iter_run_prog(prog, &ctx);
0803 }
0804 
0805 static int bpf_iter_ksym_seq_show(struct seq_file *m, void *p)
0806 {
0807     return ksym_prog_seq_show(m, false);
0808 }
0809 
0810 static void bpf_iter_ksym_seq_stop(struct seq_file *m, void *p)
0811 {
0812     if (!p)
0813         (void) ksym_prog_seq_show(m, true);
0814     else
0815         s_stop(m, p);
0816 }
0817 
0818 static const struct seq_operations bpf_iter_ksym_ops = {
0819     .start = s_start,
0820     .next = s_next,
0821     .stop = bpf_iter_ksym_seq_stop,
0822     .show = bpf_iter_ksym_seq_show,
0823 };
0824 
0825 static int bpf_iter_ksym_init(void *priv_data, struct bpf_iter_aux_info *aux)
0826 {
0827     struct kallsym_iter *iter = priv_data;
0828 
0829     reset_iter(iter, 0);
0830 
0831     /* cache here as in kallsyms_open() case; use current process
0832      * credentials to tell BPF iterators if values should be shown.
0833      */
0834     iter->show_value = kallsyms_show_value(current_cred());
0835 
0836     return 0;
0837 }
0838 
0839 DEFINE_BPF_ITER_FUNC(ksym, struct bpf_iter_meta *meta, struct kallsym_iter *ksym)
0840 
0841 static const struct bpf_iter_seq_info ksym_iter_seq_info = {
0842     .seq_ops        = &bpf_iter_ksym_ops,
0843     .init_seq_private   = bpf_iter_ksym_init,
0844     .fini_seq_private   = NULL,
0845     .seq_priv_size      = sizeof(struct kallsym_iter),
0846 };
0847 
0848 static struct bpf_iter_reg ksym_iter_reg_info = {
0849     .target                 = "ksym",
0850     .feature        = BPF_ITER_RESCHED,
0851     .ctx_arg_info_size  = 1,
0852     .ctx_arg_info       = {
0853         { offsetof(struct bpf_iter__ksym, ksym),
0854           PTR_TO_BTF_ID_OR_NULL },
0855     },
0856     .seq_info       = &ksym_iter_seq_info,
0857 };
0858 
0859 BTF_ID_LIST(btf_ksym_iter_id)
0860 BTF_ID(struct, kallsym_iter)
0861 
0862 static int __init bpf_ksym_iter_register(void)
0863 {
0864     ksym_iter_reg_info.ctx_arg_info[0].btf_id = *btf_ksym_iter_id;
0865     return bpf_iter_reg_target(&ksym_iter_reg_info);
0866 }
0867 
0868 late_initcall(bpf_ksym_iter_register);
0869 
0870 #endif /* CONFIG_BPF_SYSCALL */
0871 
0872 static inline int kallsyms_for_perf(void)
0873 {
0874 #ifdef CONFIG_PERF_EVENTS
0875     extern int sysctl_perf_event_paranoid;
0876     if (sysctl_perf_event_paranoid <= 1)
0877         return 1;
0878 #endif
0879     return 0;
0880 }
0881 
0882 /*
0883  * We show kallsyms information even to normal users if we've enabled
0884  * kernel profiling and are explicitly not paranoid (so kptr_restrict
0885  * is clear, and sysctl_perf_event_paranoid isn't set).
0886  *
0887  * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
0888  * block even that).
0889  */
0890 bool kallsyms_show_value(const struct cred *cred)
0891 {
0892     switch (kptr_restrict) {
0893     case 0:
0894         if (kallsyms_for_perf())
0895             return true;
0896         fallthrough;
0897     case 1:
0898         if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
0899                      CAP_OPT_NOAUDIT) == 0)
0900             return true;
0901         fallthrough;
0902     default:
0903         return false;
0904     }
0905 }
0906 
0907 static int kallsyms_open(struct inode *inode, struct file *file)
0908 {
0909     /*
0910      * We keep iterator in m->private, since normal case is to
0911      * s_start from where we left off, so we avoid doing
0912      * using get_symbol_offset for every symbol.
0913      */
0914     struct kallsym_iter *iter;
0915     iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
0916     if (!iter)
0917         return -ENOMEM;
0918     reset_iter(iter, 0);
0919 
0920     /*
0921      * Instead of checking this on every s_show() call, cache
0922      * the result here at open time.
0923      */
0924     iter->show_value = kallsyms_show_value(file->f_cred);
0925     return 0;
0926 }
0927 
0928 #ifdef  CONFIG_KGDB_KDB
0929 const char *kdb_walk_kallsyms(loff_t *pos)
0930 {
0931     static struct kallsym_iter kdb_walk_kallsyms_iter;
0932     if (*pos == 0) {
0933         memset(&kdb_walk_kallsyms_iter, 0,
0934                sizeof(kdb_walk_kallsyms_iter));
0935         reset_iter(&kdb_walk_kallsyms_iter, 0);
0936     }
0937     while (1) {
0938         if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
0939             return NULL;
0940         ++*pos;
0941         /* Some debugging symbols have no name.  Ignore them. */
0942         if (kdb_walk_kallsyms_iter.name[0])
0943             return kdb_walk_kallsyms_iter.name;
0944     }
0945 }
0946 #endif  /* CONFIG_KGDB_KDB */
0947 
0948 static const struct proc_ops kallsyms_proc_ops = {
0949     .proc_open  = kallsyms_open,
0950     .proc_read  = seq_read,
0951     .proc_lseek = seq_lseek,
0952     .proc_release   = seq_release_private,
0953 };
0954 
0955 static int __init kallsyms_init(void)
0956 {
0957     proc_create("kallsyms", 0444, NULL, &kallsyms_proc_ops);
0958     return 0;
0959 }
0960 device_initcall(kallsyms_init);