Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
4 : *
5 : * Rewritten and vastly simplified by Rusty Russell for in-kernel
6 : * module loader:
7 : * Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
8 : *
9 : * ChangeLog:
10 : *
11 : * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
12 : * Changed the compression method from stem compression to "table lookup"
13 : * compression (see scripts/kallsyms.c for a more complete description)
14 : */
15 : #include <linux/kallsyms.h>
16 : #include <linux/init.h>
17 : #include <linux/seq_file.h>
18 : #include <linux/fs.h>
19 : #include <linux/kdb.h>
20 : #include <linux/err.h>
21 : #include <linux/proc_fs.h>
22 : #include <linux/sched.h> /* for cond_resched */
23 : #include <linux/ctype.h>
24 : #include <linux/slab.h>
25 : #include <linux/filter.h>
26 : #include <linux/ftrace.h>
27 : #include <linux/kprobes.h>
28 : #include <linux/compiler.h>
29 :
30 : /*
31 : * These will be re-linked against their real values
32 : * during the second link stage.
33 : */
34 : extern const unsigned long kallsyms_addresses[] __weak;
35 : extern const int kallsyms_offsets[] __weak;
36 : extern const u8 kallsyms_names[] __weak;
37 :
38 : /*
39 : * Tell the compiler that the count isn't in the small data section if the arch
40 : * has one (eg: FRV).
41 : */
42 : extern const unsigned int kallsyms_num_syms
43 : __section(".rodata") __attribute__((weak));
44 :
45 : extern const unsigned long kallsyms_relative_base
46 : __section(".rodata") __attribute__((weak));
47 :
48 : extern const char kallsyms_token_table[] __weak;
49 : extern const u16 kallsyms_token_index[] __weak;
50 :
51 : extern const unsigned int kallsyms_markers[] __weak;
52 :
53 : /*
54 : * Expand a compressed symbol data into the resulting uncompressed string,
55 : * if uncompressed string is too long (>= maxlen), it will be truncated,
56 : * given the offset to where the symbol is in the compressed stream.
57 : */
58 80 : static unsigned int kallsyms_expand_symbol(unsigned int off,
59 : char *result, size_t maxlen)
60 : {
61 80 : int len, skipped_first = 0;
62 80 : const char *tptr;
63 80 : const u8 *data;
64 :
65 : /* Get the compressed symbol length from the first symbol byte. */
66 80 : data = &kallsyms_names[off];
67 80 : len = *data;
68 80 : data++;
69 :
70 : /*
71 : * Update the offset to return the offset for the next symbol on
72 : * the compressed stream.
73 : */
74 80 : off += len + 1;
75 :
76 : /*
77 : * For every byte on the compressed symbol data, copy the table
78 : * entry for that byte.
79 : */
80 874 : while (len) {
81 794 : tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
82 794 : data++;
83 794 : len--;
84 :
85 2202 : while (*tptr) {
86 1408 : if (skipped_first) {
87 1328 : if (maxlen <= 1)
88 0 : goto tail;
89 1328 : *result = *tptr;
90 1328 : result++;
91 1328 : maxlen--;
92 : } else
93 : skipped_first = 1;
94 1408 : tptr++;
95 : }
96 : }
97 :
98 80 : tail:
99 80 : if (maxlen)
100 80 : *result = '\0';
101 :
102 : /* Return to offset to the next symbol. */
103 80 : return off;
104 : }
105 :
106 : /*
107 : * Get symbol type information. This is encoded as a single char at the
108 : * beginning of the symbol name.
109 : */
110 0 : static char kallsyms_get_symbol_type(unsigned int off)
111 : {
112 : /*
113 : * Get just the first code, look it up in the token table,
114 : * and return the first char from this token.
115 : */
116 0 : return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
117 : }
118 :
119 :
120 : /*
121 : * Find the offset on the compressed stream given and index in the
122 : * kallsyms array.
123 : */
124 80 : static unsigned int get_symbol_offset(unsigned long pos)
125 : {
126 80 : const u8 *name;
127 80 : int i;
128 :
129 : /*
130 : * Use the closest marker we have. We have markers every 256 positions,
131 : * so that should be close enough.
132 : */
133 80 : name = &kallsyms_names[kallsyms_markers[pos >> 8]];
134 :
135 : /*
136 : * Sequentially scan all the symbols up to the point we're searching
137 : * for. Every symbol is stored in a [<len>][<len> bytes of data] format,
138 : * so we just need to add the len to the current pointer for every
139 : * symbol we wish to skip.
140 : */
141 12208 : for (i = 0; i < (pos & 0xFF); i++)
142 12128 : name = name + (*name) + 1;
143 :
144 80 : return name - kallsyms_names;
145 : }
146 :
147 1756 : static unsigned long kallsyms_sym_address(int idx)
148 : {
149 1756 : if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
150 : return kallsyms_addresses[idx];
151 :
152 : /* values are unsigned offsets if --absolute-percpu is not in effect */
153 1756 : if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
154 : return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
155 :
156 : /* ...otherwise, positive offsets are absolute values */
157 1756 : if (kallsyms_offsets[idx] >= 0)
158 0 : return kallsyms_offsets[idx];
159 :
160 : /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
161 1676 : return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
162 : }
163 :
164 : /* Lookup the address for this symbol. Returns 0 if not found. */
165 0 : unsigned long kallsyms_lookup_name(const char *name)
166 : {
167 0 : char namebuf[KSYM_NAME_LEN];
168 0 : unsigned long i;
169 0 : unsigned int off;
170 :
171 0 : for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
172 0 : off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
173 :
174 0 : if (strcmp(namebuf, name) == 0)
175 0 : return kallsyms_sym_address(i);
176 : }
177 0 : return module_kallsyms_lookup_name(name);
178 : }
179 :
180 : #ifdef CONFIG_LIVEPATCH
181 : /*
182 : * Iterate over all symbols in vmlinux. For symbols from modules use
183 : * module_kallsyms_on_each_symbol instead.
184 : */
185 : int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
186 : unsigned long),
187 : void *data)
188 : {
189 : char namebuf[KSYM_NAME_LEN];
190 : unsigned long i;
191 : unsigned int off;
192 : int ret;
193 :
194 : for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
195 : off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
196 : ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
197 : if (ret != 0)
198 : return ret;
199 : }
200 : return 0;
201 : }
202 : #endif /* CONFIG_LIVEPATCH */
203 :
204 80 : static unsigned long get_symbol_pos(unsigned long addr,
205 : unsigned long *symbolsize,
206 : unsigned long *offset)
207 : {
208 80 : unsigned long symbol_start = 0, symbol_end = 0;
209 80 : unsigned long i, low, high, mid;
210 :
211 : /* This kernel should never had been booted. */
212 80 : if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
213 : BUG_ON(!kallsyms_addresses);
214 : else
215 80 : BUG_ON(!kallsyms_offsets);
216 :
217 : /* Do a binary search on the sorted kallsyms_addresses array. */
218 80 : low = 0;
219 80 : high = kallsyms_num_syms;
220 :
221 1510 : while (high - low > 1) {
222 1350 : mid = low + (high - low) / 2;
223 2700 : if (kallsyms_sym_address(mid) <= addr)
224 : low = mid;
225 : else
226 856 : high = mid;
227 : }
228 :
229 : /*
230 : * Search for the first aliased symbol. Aliased
231 : * symbols are symbols with the same address.
232 : */
233 246 : while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
234 2 : --low;
235 :
236 80 : symbol_start = kallsyms_sym_address(low);
237 :
238 : /* Search for next non-aliased symbol. */
239 82 : for (i = low + 1; i < kallsyms_num_syms; i++) {
240 164 : if (kallsyms_sym_address(i) > symbol_start) {
241 80 : symbol_end = kallsyms_sym_address(i);
242 : break;
243 : }
244 : }
245 :
246 : /* If we found no next symbol, we use the end of the section. */
247 80 : if (!symbol_end) {
248 0 : if (is_kernel_inittext(addr))
249 : symbol_end = (unsigned long)_einittext;
250 0 : else if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
251 0 : symbol_end = (unsigned long)_end;
252 : else
253 : symbol_end = (unsigned long)_etext;
254 : }
255 :
256 80 : if (symbolsize)
257 80 : *symbolsize = symbol_end - symbol_start;
258 80 : if (offset)
259 80 : *offset = addr - symbol_start;
260 :
261 80 : return low;
262 : }
263 :
264 : /*
265 : * Lookup an address but don't bother to find any names.
266 : */
267 0 : int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
268 : unsigned long *offset)
269 : {
270 0 : char namebuf[KSYM_NAME_LEN];
271 :
272 0 : if (is_ksym_addr(addr)) {
273 0 : get_symbol_pos(addr, symbolsize, offset);
274 0 : return 1;
275 : }
276 0 : return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
277 0 : !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
278 : }
279 :
280 : /*
281 : * Lookup an address
282 : * - modname is set to NULL if it's in the kernel.
283 : * - We guarantee that the returned name is valid until we reschedule even if.
284 : * It resides in a module.
285 : * - We also guarantee that modname will be valid until rescheduled.
286 : */
287 82 : const char *kallsyms_lookup(unsigned long addr,
288 : unsigned long *symbolsize,
289 : unsigned long *offset,
290 : char **modname, char *namebuf)
291 : {
292 82 : const char *ret;
293 :
294 82 : namebuf[KSYM_NAME_LEN - 1] = 0;
295 82 : namebuf[0] = 0;
296 :
297 82 : if (is_ksym_addr(addr)) {
298 80 : unsigned long pos;
299 :
300 80 : pos = get_symbol_pos(addr, symbolsize, offset);
301 : /* Grab name */
302 80 : kallsyms_expand_symbol(get_symbol_offset(pos),
303 : namebuf, KSYM_NAME_LEN);
304 80 : if (modname)
305 80 : *modname = NULL;
306 80 : return namebuf;
307 : }
308 :
309 : /* See if it's in a module or a BPF JITed image. */
310 82 : ret = module_address_lookup(addr, symbolsize, offset,
311 : modname, namebuf);
312 : if (!ret)
313 82 : ret = bpf_address_lookup(addr, symbolsize,
314 : offset, modname, namebuf);
315 :
316 : if (!ret)
317 82 : ret = ftrace_mod_address_lookup(addr, symbolsize,
318 : offset, modname, namebuf);
319 : return ret;
320 : }
321 :
322 0 : int lookup_symbol_name(unsigned long addr, char *symname)
323 : {
324 0 : symname[0] = '\0';
325 0 : symname[KSYM_NAME_LEN - 1] = '\0';
326 :
327 0 : if (is_ksym_addr(addr)) {
328 0 : unsigned long pos;
329 :
330 0 : pos = get_symbol_pos(addr, NULL, NULL);
331 : /* Grab name */
332 0 : kallsyms_expand_symbol(get_symbol_offset(pos),
333 : symname, KSYM_NAME_LEN);
334 0 : return 0;
335 : }
336 : /* See if it's in a module. */
337 0 : return lookup_module_symbol_name(addr, symname);
338 : }
339 :
340 0 : int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
341 : unsigned long *offset, char *modname, char *name)
342 : {
343 0 : name[0] = '\0';
344 0 : name[KSYM_NAME_LEN - 1] = '\0';
345 :
346 0 : if (is_ksym_addr(addr)) {
347 0 : unsigned long pos;
348 :
349 0 : pos = get_symbol_pos(addr, size, offset);
350 : /* Grab name */
351 0 : kallsyms_expand_symbol(get_symbol_offset(pos),
352 : name, KSYM_NAME_LEN);
353 0 : modname[0] = '\0';
354 0 : return 0;
355 : }
356 : /* See if it's in a module. */
357 0 : return lookup_module_symbol_attrs(addr, size, offset, modname, name);
358 : }
359 :
360 : /* Look up a kernel symbol and return it in a text buffer. */
361 82 : static int __sprint_symbol(char *buffer, unsigned long address,
362 : int symbol_offset, int add_offset)
363 : {
364 82 : char *modname;
365 82 : const char *name;
366 82 : unsigned long offset, size;
367 82 : int len;
368 :
369 82 : address += symbol_offset;
370 82 : name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
371 82 : if (!name)
372 2 : return sprintf(buffer, "0x%lx", address - symbol_offset);
373 :
374 80 : if (name != buffer)
375 0 : strcpy(buffer, name);
376 80 : len = strlen(buffer);
377 80 : offset -= symbol_offset;
378 :
379 80 : if (add_offset)
380 80 : len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
381 :
382 80 : if (modname)
383 0 : len += sprintf(buffer + len, " [%s]", modname);
384 :
385 : return len;
386 : }
387 :
388 : /**
389 : * sprint_symbol - Look up a kernel symbol and return it in a text buffer
390 : * @buffer: buffer to be stored
391 : * @address: address to lookup
392 : *
393 : * This function looks up a kernel symbol with @address and stores its name,
394 : * offset, size and module name to @buffer if possible. If no symbol was found,
395 : * just saves its @address as is.
396 : *
397 : * This function returns the number of bytes stored in @buffer.
398 : */
399 14 : int sprint_symbol(char *buffer, unsigned long address)
400 : {
401 14 : return __sprint_symbol(buffer, address, 0, 1);
402 : }
403 : EXPORT_SYMBOL_GPL(sprint_symbol);
404 :
405 : /**
406 : * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
407 : * @buffer: buffer to be stored
408 : * @address: address to lookup
409 : *
410 : * This function looks up a kernel symbol with @address and stores its name
411 : * and module name to @buffer if possible. If no symbol was found, just saves
412 : * its @address as is.
413 : *
414 : * This function returns the number of bytes stored in @buffer.
415 : */
416 0 : int sprint_symbol_no_offset(char *buffer, unsigned long address)
417 : {
418 0 : return __sprint_symbol(buffer, address, 0, 0);
419 : }
420 : EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
421 :
422 : /**
423 : * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
424 : * @buffer: buffer to be stored
425 : * @address: address to lookup
426 : *
427 : * This function is for stack backtrace and does the same thing as
428 : * sprint_symbol() but with modified/decreased @address. If there is a
429 : * tail-call to the function marked "noreturn", gcc optimized out code after
430 : * the call so that the stack-saved return address could point outside of the
431 : * caller. This function ensures that kallsyms will find the original caller
432 : * by decreasing @address.
433 : *
434 : * This function returns the number of bytes stored in @buffer.
435 : */
436 68 : int sprint_backtrace(char *buffer, unsigned long address)
437 : {
438 68 : return __sprint_symbol(buffer, address, -1, 1);
439 : }
440 :
441 : /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
442 : struct kallsym_iter {
443 : loff_t pos;
444 : loff_t pos_arch_end;
445 : loff_t pos_mod_end;
446 : loff_t pos_ftrace_mod_end;
447 : loff_t pos_bpf_end;
448 : unsigned long value;
449 : unsigned int nameoff; /* If iterating in core kernel symbols. */
450 : char type;
451 : char name[KSYM_NAME_LEN];
452 : char module_name[MODULE_NAME_LEN];
453 : int exported;
454 : int show_value;
455 : };
456 :
457 0 : int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
458 : char *type, char *name)
459 : {
460 0 : return -EINVAL;
461 : }
462 :
463 0 : static int get_ksymbol_arch(struct kallsym_iter *iter)
464 : {
465 0 : int ret = arch_get_kallsym(iter->pos - kallsyms_num_syms,
466 : &iter->value, &iter->type,
467 0 : iter->name);
468 :
469 0 : if (ret < 0) {
470 0 : iter->pos_arch_end = iter->pos;
471 0 : return 0;
472 : }
473 :
474 : return 1;
475 : }
476 :
477 0 : static int get_ksymbol_mod(struct kallsym_iter *iter)
478 : {
479 0 : int ret = module_get_kallsym(iter->pos - iter->pos_arch_end,
480 : &iter->value, &iter->type,
481 0 : iter->name, iter->module_name,
482 : &iter->exported);
483 0 : if (ret < 0) {
484 0 : iter->pos_mod_end = iter->pos;
485 0 : return 0;
486 : }
487 :
488 : return 1;
489 : }
490 :
491 : /*
492 : * ftrace_mod_get_kallsym() may also get symbols for pages allocated for ftrace
493 : * purposes. In that case "__builtin__ftrace" is used as a module name, even
494 : * though "__builtin__ftrace" is not a module.
495 : */
496 0 : static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter)
497 : {
498 0 : int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end,
499 : &iter->value, &iter->type,
500 0 : iter->name, iter->module_name,
501 : &iter->exported);
502 0 : if (ret < 0) {
503 0 : iter->pos_ftrace_mod_end = iter->pos;
504 0 : return 0;
505 : }
506 :
507 : return 1;
508 : }
509 :
510 0 : static int get_ksymbol_bpf(struct kallsym_iter *iter)
511 : {
512 0 : int ret;
513 :
514 0 : strlcpy(iter->module_name, "bpf", MODULE_NAME_LEN);
515 0 : iter->exported = 0;
516 0 : ret = bpf_get_kallsym(iter->pos - iter->pos_ftrace_mod_end,
517 : &iter->value, &iter->type,
518 0 : iter->name);
519 0 : if (ret < 0) {
520 0 : iter->pos_bpf_end = iter->pos;
521 0 : return 0;
522 : }
523 :
524 : return 1;
525 : }
526 :
527 : /*
528 : * This uses "__builtin__kprobes" as a module name for symbols for pages
529 : * allocated for kprobes' purposes, even though "__builtin__kprobes" is not a
530 : * module.
531 : */
532 0 : static int get_ksymbol_kprobe(struct kallsym_iter *iter)
533 : {
534 0 : strlcpy(iter->module_name, "__builtin__kprobes", MODULE_NAME_LEN);
535 0 : iter->exported = 0;
536 0 : return kprobe_get_kallsym(iter->pos - iter->pos_bpf_end,
537 : &iter->value, &iter->type,
538 0 : iter->name) < 0 ? 0 : 1;
539 : }
540 :
541 : /* Returns space to next name. */
542 0 : static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
543 : {
544 0 : unsigned off = iter->nameoff;
545 :
546 0 : iter->module_name[0] = '\0';
547 0 : iter->value = kallsyms_sym_address(iter->pos);
548 :
549 0 : iter->type = kallsyms_get_symbol_type(off);
550 :
551 0 : off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
552 :
553 0 : return off - iter->nameoff;
554 : }
555 :
556 0 : static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
557 : {
558 0 : iter->name[0] = '\0';
559 0 : iter->nameoff = get_symbol_offset(new_pos);
560 0 : iter->pos = new_pos;
561 0 : if (new_pos == 0) {
562 0 : iter->pos_arch_end = 0;
563 0 : iter->pos_mod_end = 0;
564 0 : iter->pos_ftrace_mod_end = 0;
565 0 : iter->pos_bpf_end = 0;
566 : }
567 0 : }
568 :
569 : /*
570 : * The end position (last + 1) of each additional kallsyms section is recorded
571 : * in iter->pos_..._end as each section is added, and so can be used to
572 : * determine which get_ksymbol_...() function to call next.
573 : */
574 0 : static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
575 : {
576 0 : iter->pos = pos;
577 :
578 0 : if ((!iter->pos_arch_end || iter->pos_arch_end > pos) &&
579 0 : get_ksymbol_arch(iter))
580 : return 1;
581 :
582 0 : if ((!iter->pos_mod_end || iter->pos_mod_end > pos) &&
583 0 : get_ksymbol_mod(iter))
584 : return 1;
585 :
586 0 : if ((!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > pos) &&
587 0 : get_ksymbol_ftrace_mod(iter))
588 : return 1;
589 :
590 0 : if ((!iter->pos_bpf_end || iter->pos_bpf_end > pos) &&
591 0 : get_ksymbol_bpf(iter))
592 : return 1;
593 :
594 0 : return get_ksymbol_kprobe(iter);
595 : }
596 :
597 : /* Returns false if pos at or past end of file. */
598 0 : static int update_iter(struct kallsym_iter *iter, loff_t pos)
599 : {
600 : /* Module symbols can be accessed randomly. */
601 0 : if (pos >= kallsyms_num_syms)
602 0 : return update_iter_mod(iter, pos);
603 :
604 : /* If we're not on the desired position, reset to new position. */
605 0 : if (pos != iter->pos)
606 0 : reset_iter(iter, pos);
607 :
608 0 : iter->nameoff += get_ksymbol_core(iter);
609 0 : iter->pos++;
610 :
611 0 : return 1;
612 : }
613 :
614 0 : static void *s_next(struct seq_file *m, void *p, loff_t *pos)
615 : {
616 0 : (*pos)++;
617 :
618 0 : if (!update_iter(m->private, *pos))
619 0 : return NULL;
620 : return p;
621 : }
622 :
623 0 : static void *s_start(struct seq_file *m, loff_t *pos)
624 : {
625 0 : if (!update_iter(m->private, *pos))
626 : return NULL;
627 0 : return m->private;
628 : }
629 :
630 0 : static void s_stop(struct seq_file *m, void *p)
631 : {
632 0 : }
633 :
634 0 : static int s_show(struct seq_file *m, void *p)
635 : {
636 0 : void *value;
637 0 : struct kallsym_iter *iter = m->private;
638 :
639 : /* Some debugging symbols have no name. Ignore them. */
640 0 : if (!iter->name[0])
641 : return 0;
642 :
643 0 : value = iter->show_value ? (void *)iter->value : NULL;
644 :
645 0 : if (iter->module_name[0]) {
646 0 : char type;
647 :
648 : /*
649 : * Label it "global" if it is exported,
650 : * "local" if not exported.
651 : */
652 0 : type = iter->exported ? toupper(iter->type) :
653 0 : tolower(iter->type);
654 0 : seq_printf(m, "%px %c %s\t[%s]\n", value,
655 0 : type, iter->name, iter->module_name);
656 : } else
657 0 : seq_printf(m, "%px %c %s\n", value,
658 0 : iter->type, iter->name);
659 : return 0;
660 : }
661 :
662 : static const struct seq_operations kallsyms_op = {
663 : .start = s_start,
664 : .next = s_next,
665 : .stop = s_stop,
666 : .show = s_show
667 : };
668 :
669 0 : static inline int kallsyms_for_perf(void)
670 : {
671 : #ifdef CONFIG_PERF_EVENTS
672 0 : extern int sysctl_perf_event_paranoid;
673 0 : if (sysctl_perf_event_paranoid <= 1)
674 : return 1;
675 : #endif
676 : return 0;
677 : }
678 :
679 : /*
680 : * We show kallsyms information even to normal users if we've enabled
681 : * kernel profiling and are explicitly not paranoid (so kptr_restrict
682 : * is clear, and sysctl_perf_event_paranoid isn't set).
683 : *
684 : * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
685 : * block even that).
686 : */
687 0 : bool kallsyms_show_value(const struct cred *cred)
688 : {
689 0 : switch (kptr_restrict) {
690 : case 0:
691 0 : if (kallsyms_for_perf())
692 : return true;
693 0 : fallthrough;
694 : case 1:
695 0 : if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
696 : CAP_OPT_NOAUDIT) == 0)
697 0 : return true;
698 : fallthrough;
699 : default:
700 : return false;
701 : }
702 : }
703 :
704 0 : static int kallsyms_open(struct inode *inode, struct file *file)
705 : {
706 : /*
707 : * We keep iterator in m->private, since normal case is to
708 : * s_start from where we left off, so we avoid doing
709 : * using get_symbol_offset for every symbol.
710 : */
711 0 : struct kallsym_iter *iter;
712 0 : iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
713 0 : if (!iter)
714 : return -ENOMEM;
715 0 : reset_iter(iter, 0);
716 :
717 : /*
718 : * Instead of checking this on every s_show() call, cache
719 : * the result here at open time.
720 : */
721 0 : iter->show_value = kallsyms_show_value(file->f_cred);
722 0 : return 0;
723 : }
724 :
725 : #ifdef CONFIG_KGDB_KDB
726 : const char *kdb_walk_kallsyms(loff_t *pos)
727 : {
728 : static struct kallsym_iter kdb_walk_kallsyms_iter;
729 : if (*pos == 0) {
730 : memset(&kdb_walk_kallsyms_iter, 0,
731 : sizeof(kdb_walk_kallsyms_iter));
732 : reset_iter(&kdb_walk_kallsyms_iter, 0);
733 : }
734 : while (1) {
735 : if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
736 : return NULL;
737 : ++*pos;
738 : /* Some debugging symbols have no name. Ignore them. */
739 : if (kdb_walk_kallsyms_iter.name[0])
740 : return kdb_walk_kallsyms_iter.name;
741 : }
742 : }
743 : #endif /* CONFIG_KGDB_KDB */
744 :
745 : static const struct proc_ops kallsyms_proc_ops = {
746 : .proc_open = kallsyms_open,
747 : .proc_read = seq_read,
748 : .proc_lseek = seq_lseek,
749 : .proc_release = seq_release_private,
750 : };
751 :
752 1 : static int __init kallsyms_init(void)
753 : {
754 1 : proc_create("kallsyms", 0444, NULL, &kallsyms_proc_ops);
755 1 : return 0;
756 : }
757 : device_initcall(kallsyms_init);
|