Commit 16025184 authored by Kees Cook's avatar Kees Cook

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: stable@vger.kernel.org
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
parent 48778464
...@@ -889,7 +889,7 @@ static inline bool bpf_dump_raw_ok(void) ...@@ -889,7 +889,7 @@ static inline bool bpf_dump_raw_ok(void)
/* Reconstruction of call-sites is dependent on kallsyms, /* Reconstruction of call-sites is dependent on kallsyms,
* thus make dump the same restriction. * thus make dump the same restriction.
*/ */
return kallsyms_show_value() == 1; return kallsyms_show_value(current_cred());
} }
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1) 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
struct cred;
struct module; struct module;
static inline int is_kernel_inittext(unsigned long addr) static inline int is_kernel_inittext(unsigned long addr)
...@@ -98,7 +99,7 @@ int lookup_symbol_name(unsigned long addr, char *symname); ...@@ -98,7 +99,7 @@ int lookup_symbol_name(unsigned long addr, char *symname);
int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
/* How and when do we show kallsyms values? */ /* How and when do we show kallsyms values? */
extern int kallsyms_show_value(void); extern bool kallsyms_show_value(const struct cred *cred);
#else /* !CONFIG_KALLSYMS */ #else /* !CONFIG_KALLSYMS */
...@@ -158,7 +159,7 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u ...@@ -158,7 +159,7 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u
return -ERANGE; return -ERANGE;
} }
static inline int kallsyms_show_value(void) static inline bool kallsyms_show_value(const struct cred *cred)
{ {
return false; return false;
} }
......
...@@ -644,19 +644,20 @@ static inline int kallsyms_for_perf(void) ...@@ -644,19 +644,20 @@ static inline int kallsyms_for_perf(void)
* Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
* block even that). * block even that).
*/ */
int kallsyms_show_value(void) bool kallsyms_show_value(const struct cred *cred)
{ {
switch (kptr_restrict) { switch (kptr_restrict) {
case 0: case 0:
if (kallsyms_for_perf()) if (kallsyms_for_perf())
return 1; return true;
/* fallthrough */ /* fallthrough */
case 1: case 1:
if (has_capability_noaudit(current, CAP_SYSLOG)) if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
return 1; CAP_OPT_NOAUDIT) == 0)
return true;
/* fallthrough */ /* fallthrough */
default: default:
return 0; return false;
} }
} }
...@@ -673,7 +674,11 @@ static int kallsyms_open(struct inode *inode, struct file *file) ...@@ -673,7 +674,11 @@ static int kallsyms_open(struct inode *inode, struct file *file)
return -ENOMEM; return -ENOMEM;
reset_iter(iter, 0); reset_iter(iter, 0);
iter->show_value = kallsyms_show_value(); /*
* Instead of checking this on every s_show() call, cache
* the result here at open time.
*/
iter->show_value = kallsyms_show_value(file->f_cred);
return 0; return 0;
} }
......
...@@ -2448,7 +2448,7 @@ static void report_probe(struct seq_file *pi, struct kprobe *p, ...@@ -2448,7 +2448,7 @@ static void report_probe(struct seq_file *pi, struct kprobe *p,
else else
kprobe_type = "k"; kprobe_type = "k";
if (!kallsyms_show_value()) if (!kallsyms_show_value(current_cred()))
addr = NULL; addr = NULL;
if (sym) if (sym)
...@@ -2540,7 +2540,7 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) ...@@ -2540,7 +2540,7 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v)
* If /proc/kallsyms is not showing kernel address, we won't * If /proc/kallsyms is not showing kernel address, we won't
* show them here either. * show them here either.
*/ */
if (!kallsyms_show_value()) if (!kallsyms_show_value(current_cred()))
seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL, seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL,
(void *)ent->start_addr); (void *)ent->start_addr);
else else
......
...@@ -4377,7 +4377,7 @@ static int modules_open(struct inode *inode, struct file *file) ...@@ -4377,7 +4377,7 @@ static int modules_open(struct inode *inode, struct file *file)
if (!err) { if (!err) {
struct seq_file *m = file->private_data; struct seq_file *m = file->private_data;
m->private = kallsyms_show_value() ? NULL : (void *)8ul; m->private = kallsyms_show_value(current_cred()) ? NULL : (void *)8ul;
} }
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment