Skip to content

Commit 1602518

Browse files
committed
kallsyms: Refactor kallsyms_show_value() to take cred
In order to perform future tests against the cred saved during open(), switch kallsyms_show_value() to operate on a cred, and have all current callers pass current_cred(). This makes it very obvious where callers are checking the wrong credential in their "read" contexts. These will be fixed in the coming patches. Additionally switch return value to bool, since it is always used as a direct permission check, not a 0-on-success, negative-on-error style function return. Cc: [email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 4877846 commit 1602518

File tree

5 files changed

+18
-12
lines changed

5 files changed

+18
-12
lines changed

include/linux/filter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ static inline bool bpf_dump_raw_ok(void)
889889
/* Reconstruction of call-sites is dependent on kallsyms,
890890
* thus make dump the same restriction.
891891
*/
892-
return kallsyms_show_value() == 1;
892+
return kallsyms_show_value(current_cred());
893893
}
894894

895895
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,

include/linux/kallsyms.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
1919
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
2020

21+
struct cred;
2122
struct module;
2223

2324
static inline int is_kernel_inittext(unsigned long addr)
@@ -98,7 +99,7 @@ int lookup_symbol_name(unsigned long addr, char *symname);
9899
int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
99100

100101
/* How and when do we show kallsyms values? */
101-
extern int kallsyms_show_value(void);
102+
extern bool kallsyms_show_value(const struct cred *cred);
102103

103104
#else /* !CONFIG_KALLSYMS */
104105

@@ -158,7 +159,7 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u
158159
return -ERANGE;
159160
}
160161

161-
static inline int kallsyms_show_value(void)
162+
static inline bool kallsyms_show_value(const struct cred *cred)
162163
{
163164
return false;
164165
}

kernel/kallsyms.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -644,19 +644,20 @@ static inline int kallsyms_for_perf(void)
644644
* Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
645645
* block even that).
646646
*/
647-
int kallsyms_show_value(void)
647+
bool kallsyms_show_value(const struct cred *cred)
648648
{
649649
switch (kptr_restrict) {
650650
case 0:
651651
if (kallsyms_for_perf())
652-
return 1;
652+
return true;
653653
/* fallthrough */
654654
case 1:
655-
if (has_capability_noaudit(current, CAP_SYSLOG))
656-
return 1;
655+
if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
656+
CAP_OPT_NOAUDIT) == 0)
657+
return true;
657658
/* fallthrough */
658659
default:
659-
return 0;
660+
return false;
660661
}
661662
}
662663

@@ -673,7 +674,11 @@ static int kallsyms_open(struct inode *inode, struct file *file)
673674
return -ENOMEM;
674675
reset_iter(iter, 0);
675676

676-
iter->show_value = kallsyms_show_value();
677+
/*
678+
* Instead of checking this on every s_show() call, cache
679+
* the result here at open time.
680+
*/
681+
iter->show_value = kallsyms_show_value(file->f_cred);
677682
return 0;
678683
}
679684

kernel/kprobes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,7 +2448,7 @@ static void report_probe(struct seq_file *pi, struct kprobe *p,
24482448
else
24492449
kprobe_type = "k";
24502450

2451-
if (!kallsyms_show_value())
2451+
if (!kallsyms_show_value(current_cred()))
24522452
addr = NULL;
24532453

24542454
if (sym)
@@ -2540,7 +2540,7 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v)
25402540
* If /proc/kallsyms is not showing kernel address, we won't
25412541
* show them here either.
25422542
*/
2543-
if (!kallsyms_show_value())
2543+
if (!kallsyms_show_value(current_cred()))
25442544
seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL,
25452545
(void *)ent->start_addr);
25462546
else

kernel/module.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4377,7 +4377,7 @@ static int modules_open(struct inode *inode, struct file *file)
43774377

43784378
if (!err) {
43794379
struct seq_file *m = file->private_data;
4380-
m->private = kallsyms_show_value() ? NULL : (void *)8ul;
4380+
m->private = kallsyms_show_value(current_cred()) ? NULL : (void *)8ul;
43814381
}
43824382

43834383
return err;

0 commit comments

Comments
 (0)