4 For general security related questions of perf_event_open() syscall usage,
5 performance monitoring and observability operations by Perf see here:
6 https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html
8 Enabling LSM based mandatory access control (MAC) to perf_event_open() syscall
9 ==============================================================================
11 LSM hooks for mandatory access control for perf_event_open() syscall can be
12 used starting from Linux v5.3. Below are the steps to extend Fedora (v31) with
13 Targeted policy with perf_event_open() access control capabilities:
15 1. Download selinux-policy SRPM package (e.g. selinux-policy-3.14.4-48.fc31.src.rpm on FC31)
16 and install it so rpmbuild directory would exist in the current working directory:
18 # rpm -Uhv selinux-policy-3.14.4-48.fc31.src.rpm
20 2. Get into rpmbuild/SPECS directory and unpack the source code:
22 # rpmbuild -bp selinux-policy.spec
24 3. Place patch below at rpmbuild/BUILD/selinux-policy-b86eaaf4dbcf2d51dd4432df7185c0eaf3cbcc02
25 directory and apply it:
27 # patch -p1 < selinux-policy-perf-events-perfmon.patch
28 patching file policy/flask/access_vectors
29 patching file policy/flask/security_classes
30 # cat selinux-policy-perf-events-perfmon.patch
31 diff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
32 --- a/policy/flask/access_vectors 2020-02-04 18:19:53.000000000 +0300
33 +++ b/policy/flask/access_vectors 2020-02-28 23:37:25.000000000 +0300
42 @@ -1099,3 +1100,15 @@
58 diff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
59 --- a/policy/flask/security_classes 2020-02-04 18:19:53.000000000 +0300
60 +++ b/policy/flask/security_classes 2020-02-28 21:35:17.000000000 +0300
69 4. Get into rpmbuild/SPECS directory and build policy packages from patched sources:
71 # rpmbuild --noclean --noprep -ba selinux-policy.spec
75 # ls -alh rpmbuild/RPMS/noarch/
77 drwxr-xr-x. 2 root root 4.0K Mar 20 12:16 .
78 drwxr-xr-x. 3 root root 4.0K Mar 20 12:16 ..
79 -rw-r--r--. 1 root root 112K Mar 20 12:16 selinux-policy-3.14.4-48.fc31.noarch.rpm
80 -rw-r--r--. 1 root root 1.2M Mar 20 12:17 selinux-policy-devel-3.14.4-48.fc31.noarch.rpm
81 -rw-r--r--. 1 root root 2.3M Mar 20 12:17 selinux-policy-doc-3.14.4-48.fc31.noarch.rpm
82 -rw-r--r--. 1 root root 12M Mar 20 12:17 selinux-policy-minimum-3.14.4-48.fc31.noarch.rpm
83 -rw-r--r--. 1 root root 4.5M Mar 20 12:16 selinux-policy-mls-3.14.4-48.fc31.noarch.rpm
84 -rw-r--r--. 1 root root 111K Mar 20 12:16 selinux-policy-sandbox-3.14.4-48.fc31.noarch.rpm
85 -rw-r--r--. 1 root root 14M Mar 20 12:17 selinux-policy-targeted-3.14.4-48.fc31.noarch.rpm
87 5. Install SELinux packages from Fedora repo, if not already done so, and
88 update with the patched rpms above:
90 # rpm -Uhv rpmbuild/RPMS/noarch/selinux-policy-*
92 6. Enable SELinux Permissive mode for Targeted policy, if not already done so:
94 # cat /etc/selinux/config
96 # This file controls the state of SELinux on the system.
97 # SELINUX= can take one of these three values:
98 # enforcing - SELinux security policy is enforced.
99 # permissive - SELinux prints warnings instead of enforcing.
100 # disabled - No SELinux policy is loaded.
102 # SELINUXTYPE= can take one of these three values:
103 # targeted - Targeted processes are protected,
104 # minimum - Modification of targeted policy. Only selected processes are protected.
105 # mls - Multi Level Security protection.
108 7. Enable filesystem SELinux labeling at the next reboot:
110 # touch /.autorelabel
112 8. Reboot machine and it will label filesystems and load Targeted policy into the kernel;
114 9. Login and check that dmesg output doesn't mention that perf_event class is unknown to SELinux subsystem;
116 10. Check that SELinux is enabled and in Permissive mode
121 11. Turn SELinux into Enforcing mode:
127 Opening access to perf_event_open() syscall on Fedora with SELinux
128 ==================================================================
130 Access to performance monitoring and observability operations by Perf
131 can be limited for superuser or CAP_PERFMON or CAP_SYS_ADMIN privileged
132 processes. MAC policy settings (e.g. SELinux) can be loaded into the kernel
133 and prevent unauthorized access to perf_event_open() syscall. In such case
134 Perf tool provides a message similar to the one below:
138 Access to performance monitoring and observability operations is limited.
139 Enforced MAC policy settings (SELinux) can limit access to performance
140 monitoring and observability operations. Inspect system audit records for
141 more perf_event access control information and adjusting the policy.
142 Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
143 access to performance monitoring and observability operations for users
144 without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
145 perf_event_paranoid setting is -1:
146 -1: Allow use of (almost) all events by all users
147 Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
148 >= 0: Disallow raw and ftrace function tracepoint access
149 >= 1: Disallow CPU event access
150 >= 2: Disallow kernel profiling
151 To make the adjusted perf_event_paranoid setting permanent preserve it
152 in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
154 To make sure that access is limited by MAC policy settings inspect system
155 audit records using journalctl command or /var/log/audit/audit.log so the
156 output would contain AVC denied records related to perf_event:
158 # journalctl --reverse --no-pager | grep perf_event
160 python3[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t.
161 If you believe that perf should be allowed open access on perf_event labeled unconfined_t by default.
162 setroubleshoot[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t. For complete SELinux messages run: sealert -l 4595ce5b-e58f-462c-9d86-3bc2074935de
163 audit[1318098]: AVC avc: denied { open } for pid=1318098 comm="perf" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=perf_event permissive=0
165 In order to open access to perf_event_open() syscall MAC policy settings can
166 require to be extended. On SELinux system this can be done by loading a special
167 policy module extending base policy settings. Perf related policy module can
168 be generated using the system audit records about blocking perf_event access.
169 Run the command below to generate my-perf.te policy extension file with
170 perf_event related rules:
172 # ausearch -c 'perf' --raw | audit2allow -M my-perf && cat my-perf.te
178 class perf_event { cpu kernel open read tracepoint write };
181 #============= unconfined_t ==============
182 allow unconfined_t self:perf_event { cpu kernel open read tracepoint write };
184 Now compile, pack and load my-perf.pp extension module into the kernel:
186 # checkmodule -M -m -o my-perf.mod my-perf.te
187 # semodule_package -o my-perf.pp -m my-perf.mod
188 # semodule -X 300 -i my-perf.pp
190 After all those taken steps above access to perf_event_open() syscall should
191 now be allowed by the policy settings. Check access running Perf like this:
195 Performance counter stats for 'system wide':
197 36,387.41 msec cpu-clock # 7.999 CPUs utilized
198 2,629 context-switches # 0.072 K/sec
199 57 cpu-migrations # 0.002 K/sec
200 1 page-faults # 0.000 K/sec
201 263,721,559 cycles # 0.007 GHz
202 175,746,713 instructions # 0.67 insn per cycle
203 19,628,798 branches # 0.539 M/sec
204 1,259,201 branch-misses # 6.42% of all branches
206 4.549061439 seconds time elapsed
208 The generated perf-event.pp related policy extension module can be removed
209 from the kernel using this command:
211 # semodule -X 300 -r my-perf
213 Alternatively the module can be temporarily disabled and enabled back using
216 # semodule -d my-perf
217 # semodule -e my-perf
219 If something went wrong
220 =======================
222 To turn SELinux into Permissive mode:
225 To fully disable SELinux during kernel boot [3] set kernel command line parameter selinux=0
227 To remove SELinux labeling from local filesystems:
228 # find / -mount -print0 | xargs -0 setfattr -h -x security.selinux
230 To fully turn SELinux off a machine set SELINUX=disabled at /etc/selinux/config file and reboot;
235 [1] https://download-ib01.fedoraproject.org/pub/fedora/linux/updates/31/Everything/SRPMS/Packages/s/selinux-policy-3.14.4-49.fc31.src.rpm
236 [2] https://docs.fedoraproject.org/en-US/Fedora/11/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Working_with_SELinux-Enabling_and_Disabling_SELinux.html
237 [3] https://danwalsh.livejournal.com/10972.html