Skip to content

Commit c0f3ea1

Browse files
committed
stop using '%pK' for /proc/kallsyms pointer values
Not only is it annoying to have one single flag for all pointers, as if that was a global choice and all kernel pointers are the same, but %pK can't get the 'access' vs 'open' time check right anyway. So make the /proc/kallsyms pointer value code use logic specific to that particular file. We do continue to honor kptr_restrict, but the default (which is unrestricted) is changed to instead take expected users into account, and restrict access by default. Right now the only actual expected user is kernel profiling, which has a separate sysctl flag for kernel profile access. There may be others. Signed-off-by: Linus Torvalds <[email protected]>
1 parent d6a2cf0 commit c0f3ea1

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

kernel/kallsyms.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ struct kallsym_iter {
480480
char name[KSYM_NAME_LEN];
481481
char module_name[MODULE_NAME_LEN];
482482
int exported;
483+
int show_value;
483484
};
484485

485486
static int get_ksymbol_mod(struct kallsym_iter *iter)
@@ -580,14 +581,23 @@ static void s_stop(struct seq_file *m, void *p)
580581
{
581582
}
582583

584+
#ifndef CONFIG_64BIT
585+
# define KALLSYM_FMT "%08lx"
586+
#else
587+
# define KALLSYM_FMT "%016lx"
588+
#endif
589+
583590
static int s_show(struct seq_file *m, void *p)
584591
{
592+
unsigned long value;
585593
struct kallsym_iter *iter = m->private;
586594

587595
/* Some debugging symbols have no name. Ignore them. */
588596
if (!iter->name[0])
589597
return 0;
590598

599+
value = iter->show_value ? iter->value : 0;
600+
591601
if (iter->module_name[0]) {
592602
char type;
593603

@@ -597,10 +607,10 @@ static int s_show(struct seq_file *m, void *p)
597607
*/
598608
type = iter->exported ? toupper(iter->type) :
599609
tolower(iter->type);
600-
seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
610+
seq_printf(m, KALLSYM_FMT " %c %s\t[%s]\n", value,
601611
type, iter->name, iter->module_name);
602612
} else
603-
seq_printf(m, "%pK %c %s\n", (void *)iter->value,
613+
seq_printf(m, KALLSYM_FMT " %c %s\n", value,
604614
iter->type, iter->name);
605615
return 0;
606616
}
@@ -612,6 +622,40 @@ static const struct seq_operations kallsyms_op = {
612622
.show = s_show
613623
};
614624

625+
static inline int kallsyms_for_perf(void)
626+
{
627+
#ifdef CONFIG_PERF_EVENTS
628+
extern int sysctl_perf_event_paranoid;
629+
if (sysctl_perf_event_paranoid <= 1)
630+
return 1;
631+
#endif
632+
return 0;
633+
}
634+
635+
/*
636+
* We show kallsyms information even to normal users if we've enabled
637+
* kernel profiling and are explicitly not paranoid (so kptr_restrict
638+
* is clear, and sysctl_perf_event_paranoid isn't set).
639+
*
640+
* Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
641+
* block even that).
642+
*/
643+
static int kallsyms_show_value(void)
644+
{
645+
switch (kptr_restrict) {
646+
case 0:
647+
if (kallsyms_for_perf())
648+
return 1;
649+
/* fallthrough */
650+
case 1:
651+
if (has_capability_noaudit(current, CAP_SYSLOG))
652+
return 1;
653+
/* fallthrough */
654+
default:
655+
return 0;
656+
}
657+
}
658+
615659
static int kallsyms_open(struct inode *inode, struct file *file)
616660
{
617661
/*
@@ -625,6 +669,7 @@ static int kallsyms_open(struct inode *inode, struct file *file)
625669
return -ENOMEM;
626670
reset_iter(iter, 0);
627671

672+
iter->show_value = kallsyms_show_value();
628673
return 0;
629674
}
630675

0 commit comments

Comments
 (0)