Subject: Bug#994044: CAP_PERFMON should override kernel.perf_event_paranoid=3

From: Stephan Hohe <[email-masked]>
Date: Fri, 10 Sep 2021 17:09:35 +0200

Package: linux
Version: 5.10.46-4

(Probably applies to all versions >=5.9)

Hello,

Debian adds kernel.perf_event_paranoid=3 as an additional restriction 
level for perf_event_open() 
(debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch). 
This can be overridden by the capability CAP_SYS_ADMIN.

Since the introduction of this patch, Linux introduced the new 
capability CAP_PERFMON [1] to guard access the perf_event_open() in a 
more granular way than CAT_SYS_ADMIN. Processes with CAP_PERFMON are 
intended to not be bound by kernel.perf_event_paranoid restrictions, but 
this does not currently work for kernel.perf_event_paranoid=3.

The code patched with 
security-perf-allow-further-restriction-of-perf_event_open.patch can be 
easily adjusted to also respect CAT_PERFMON by using the helper function 
perfmon_capable() in perf_event_open(). (This helper function is what 
all the other perf code uses for capability checks):

--- kernel/events/core.c.orig   2021-09-10 13:44:39.926796374 +0200
+++ kernel/events/core.c        2021-09-10 13:44:44.430640895 +0200
@@ -11696,7 +11696,7 @@
         if (flags & ~PERF_FLAG_ALL)
                 return -EINVAL;

-       if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN))
+       if (perf_paranoid_any() && !perfmon_capable())
                 return -EACCES;

         /* Do we allow access to perf_event_open(2) ? */

To test if perf_event_open() can be called successfully, a command like 
this can be used:

     sudo capsh --caps="cap_perfmon+eip 
cap_setpcap,cap_setuid,cap_setgid+ep" \
        --keep=1 --user=nobody --addamb=cap_perfmon -- perf top

This shows an error and exits if access to perf_event_open() is denied.

/Stephan

[1]: 
https://lwn.net/ml/linux-kernel/[email-masked]/