Merge tag 'trace-v4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux-2.6-block.git] / kernel / kallsyms.c
index 1966fe1c2b57fe7924a34200154f47a7911c562c..531ffa984bc262716b3412f5cfc2476c448d379f 100644 (file)
@@ -486,6 +486,7 @@ struct kallsym_iter {
        char name[KSYM_NAME_LEN];
        char module_name[MODULE_NAME_LEN];
        int exported;
+       int show_value;
 };
 
 static int get_ksymbol_mod(struct kallsym_iter *iter)
@@ -613,12 +614,15 @@ static void s_stop(struct seq_file *m, void *p)
 
 static int s_show(struct seq_file *m, void *p)
 {
+       unsigned long value;
        struct kallsym_iter *iter = m->private;
 
        /* Some debugging symbols have no name.  Ignore them. */
        if (!iter->name[0])
                return 0;
 
+       value = iter->show_value ? iter->value : 0;
+
        if (iter->module_name[0]) {
                char type;
 
@@ -628,10 +632,10 @@ static int s_show(struct seq_file *m, void *p)
                 */
                type = iter->exported ? toupper(iter->type) :
                                        tolower(iter->type);
-               seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
+               seq_printf(m, KALLSYM_FMT " %c %s\t[%s]\n", value,
                           type, iter->name, iter->module_name);
        } else
-               seq_printf(m, "%pK %c %s\n", (void *)iter->value,
+               seq_printf(m, KALLSYM_FMT " %c %s\n", value,
                           iter->type, iter->name);
        return 0;
 }
@@ -643,6 +647,40 @@ static const struct seq_operations kallsyms_op = {
        .show = s_show
 };
 
+static inline int kallsyms_for_perf(void)
+{
+#ifdef CONFIG_PERF_EVENTS
+       extern int sysctl_perf_event_paranoid;
+       if (sysctl_perf_event_paranoid <= 1)
+               return 1;
+#endif
+       return 0;
+}
+
+/*
+ * We show kallsyms information even to normal users if we've enabled
+ * kernel profiling and are explicitly not paranoid (so kptr_restrict
+ * is clear, and sysctl_perf_event_paranoid isn't set).
+ *
+ * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
+ * block even that).
+ */
+int kallsyms_show_value(void)
+{
+       switch (kptr_restrict) {
+       case 0:
+               if (kallsyms_for_perf())
+                       return 1;
+       /* fallthrough */
+       case 1:
+               if (has_capability_noaudit(current, CAP_SYSLOG))
+                       return 1;
+       /* fallthrough */
+       default:
+               return 0;
+       }
+}
+
 static int kallsyms_open(struct inode *inode, struct file *file)
 {
        /*
@@ -656,6 +694,7 @@ static int kallsyms_open(struct inode *inode, struct file *file)
                return -ENOMEM;
        reset_iter(iter, 0);
 
+       iter->show_value = kallsyms_show_value();
        return 0;
 }