systat - Restrict %rip sampling to root master
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 27 Jul 2016 23:22:11 +0000 (16:22 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 27 Jul 2016 23:22:11 +0000 (16:22 -0700)
* Only allow root to sample the %rip and %rsp on all cpus.  The sysctl will
  not sample and return 0 for these fields if the uid is not root.

  This is for security, as %rip sampling can be used to break cryptographic
  keys.

* systat -pv 1 will not display the sampling columns if the sample value
  is 0.

sys/kern/kern_clock.c
usr.bin/systat/vmmeter.c

index ccc1874..c1dbd96 100644 (file)
@@ -82,6 +82,7 @@
 #include <sys/resource.h>
 #include <sys/resourcevar.h>
 #include <sys/signalvar.h>
+#include <sys/priv.h>
 #include <sys/timex.h>
 #include <sys/timepps.h>
 #include <sys/upmap.h>
@@ -132,17 +133,29 @@ static int
 sysctl_cputime(SYSCTL_HANDLER_ARGS)
 {
        int cpu, error = 0;
+       int root_error;
        size_t size = sizeof(struct kinfo_cputime);
        struct kinfo_cputime tmp;
 
+       /*
+        * NOTE: For security reasons, only root can sniff %rip
+        */
+       root_error = priv_check_cred(curthread->td_ucred, PRIV_ROOT, 0);
+
        for (cpu = 0; cpu < ncpus; ++cpu) {
                tmp = cputime_percpu[cpu];
-               tmp.cp_sample_pc = (int64_t)globaldata_find(cpu)->gd_sample_pc;
-               tmp.cp_sample_sp = (int64_t)globaldata_find(cpu)->gd_sample_sp;
+               if (root_error == 0) {
+                       tmp.cp_sample_pc =
+                               (int64_t)globaldata_find(cpu)->gd_sample_pc;
+                       tmp.cp_sample_sp =
+                               (int64_t)globaldata_find(cpu)->gd_sample_sp;
+               }
                if ((error = SYSCTL_OUT(req, &tmp, size)) != 0)
                        break;
        }
-       smp_sniff();
+
+       if (root_error == 0)
+               smp_sniff();
 
        return (error);
 }
index 21f080d..191a05e 100644 (file)
@@ -8,6 +8,7 @@
 #include <kinfo.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
 #include <devstat.h>
 
@@ -104,10 +105,12 @@ showvmm(void)
        else
                DRAW_ROW(n, TOT_START, 8, "%*u", DTOT( v_lock_colls));
        DRAW_ROW2(n, TOT_START, 18, "%*.*s", ""); /* label */
-       DRAW_ROW2(n, TOT_START, 30, "%*.*s", ""); /* sample_pc */
+       if (getuid() == 0) {
+               DRAW_ROW2(n, TOT_START, 30, "%*.*s", ""); /* sample_pc */
 #if 0
-       DRAW_ROW2(n, TOT_START, 20, "%*.*s", ""); /* sample_sp */
+               DRAW_ROW2(n, TOT_START, 20, "%*.*s", ""); /* sample_sp */
 #endif
+       }
 
 #undef DTOT
 
@@ -172,12 +175,18 @@ do { \
 #undef CPUD
 
 #define CPUC(idx, field) vmm_cptime_cur[idx].cp_##field
-               DRAW_ROW2(n, CPU_START + i, 30, "%*.*s",
-                        address_to_symbol((void *)(intptr_t)CPUC(i, sample_pc),
-                                          &symctx));
+
+               if (vmm_cptime_cur[i].cp_sample_pc) {
+                       void *rip;
+
+                       rip = (void *)(intptr_t)CPUC(i, sample_pc);
+                       DRAW_ROW2(n, CPU_START + i, 30, "%*.*s",
+                                 address_to_symbol(rip, &symctx));
 #if 0
-               DRAW_ROW(n, CPU_START + i, 19, " %016jx", CPUC(i, sample_sp));
+                       DRAW_ROW(n, CPU_START + i, 19, " %016jx",
+                                CPUC(i, sample_sp));
 #endif
+               }
 #undef CPUC
        }
 }
@@ -213,10 +222,12 @@ labelvmm(void)
        DRAW_ROW(n, TOT_START - 1, 6, "%*s", "idle%");
        DRAW_ROW(n, TOT_START - 1, 8, "%*s", "smpcol");
        DRAW_ROW(n, TOT_START - 1, 18, "%*s", "label");
-       DRAW_ROW(n, TOT_START - 1, 30, "%*s", "sample_pc");
+       if (getuid() == 0) {
+               DRAW_ROW(n, TOT_START - 1, 30, "%*s", "sample_pc");
 #if 0
-       DRAW_ROW(n, TOT_START - 1, 18, "%*s", "sample_sp");
+               DRAW_ROW(n, TOT_START - 1, 18, "%*s", "sample_sp");
 #endif
+       }
 
        mvprintw(TOT_START, X_START, "total");
        for (i = 0; i < vmm_ncpus; ++i)