1bd7c1c66SAlexey BudankovOverview
2bd7c1c66SAlexey Budankov========
3bd7c1c66SAlexey Budankov
4bd7c1c66SAlexey BudankovFor general security related questions of perf_event_open() syscall usage,
5bd7c1c66SAlexey Budankovperformance monitoring and observability operations by Perf see here:
6bd7c1c66SAlexey Budankovhttps://www.kernel.org/doc/html/latest/admin-guide/perf-security.html
7bd7c1c66SAlexey Budankov
8bd7c1c66SAlexey BudankovEnabling LSM based mandatory access control (MAC) to perf_event_open() syscall
9bd7c1c66SAlexey Budankov==============================================================================
10bd7c1c66SAlexey Budankov
11bd7c1c66SAlexey BudankovLSM hooks for mandatory access control for perf_event_open() syscall can be
12bd7c1c66SAlexey Budankovused starting from Linux v5.3. Below are the steps to extend Fedora (v31) with
13bd7c1c66SAlexey BudankovTargeted policy with perf_event_open() access control capabilities:
14bd7c1c66SAlexey Budankov
15bd7c1c66SAlexey Budankov1. Download selinux-policy SRPM package (e.g. selinux-policy-3.14.4-48.fc31.src.rpm on FC31)
16bd7c1c66SAlexey Budankov   and install it so rpmbuild directory would exist in the current working directory:
17bd7c1c66SAlexey Budankov
18bd7c1c66SAlexey Budankov   # rpm -Uhv selinux-policy-3.14.4-48.fc31.src.rpm
19bd7c1c66SAlexey Budankov
20bd7c1c66SAlexey Budankov2. Get into rpmbuild/SPECS directory and unpack the source code:
21bd7c1c66SAlexey Budankov
22bd7c1c66SAlexey Budankov   # rpmbuild -bp selinux-policy.spec
23bd7c1c66SAlexey Budankov
24bd7c1c66SAlexey Budankov3. Place patch below at rpmbuild/BUILD/selinux-policy-b86eaaf4dbcf2d51dd4432df7185c0eaf3cbcc02
25bd7c1c66SAlexey Budankov   directory and apply it:
26bd7c1c66SAlexey Budankov
27bd7c1c66SAlexey Budankov   # patch -p1 < selinux-policy-perf-events-perfmon.patch
28bd7c1c66SAlexey Budankov   patching file policy/flask/access_vectors
29bd7c1c66SAlexey Budankov   patching file policy/flask/security_classes
30bd7c1c66SAlexey Budankov   # cat selinux-policy-perf-events-perfmon.patch
31bd7c1c66SAlexey Budankovdiff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
32bd7c1c66SAlexey Budankov--- a/policy/flask/access_vectors	2020-02-04 18:19:53.000000000 +0300
33bd7c1c66SAlexey Budankov+++ b/policy/flask/access_vectors	2020-02-28 23:37:25.000000000 +0300
34bd7c1c66SAlexey Budankov@@ -174,6 +174,7 @@
35bd7c1c66SAlexey Budankov 	wake_alarm
36bd7c1c66SAlexey Budankov 	block_suspend
37bd7c1c66SAlexey Budankov 	audit_read
38bd7c1c66SAlexey Budankov+	perfmon
39bd7c1c66SAlexey Budankov }
40bd7c1c66SAlexey Budankov
41bd7c1c66SAlexey Budankov #
42bd7c1c66SAlexey Budankov@@ -1099,3 +1100,15 @@
43bd7c1c66SAlexey Budankov
44bd7c1c66SAlexey Budankov class xdp_socket
45bd7c1c66SAlexey Budankov inherits socket
46bd7c1c66SAlexey Budankov+
47bd7c1c66SAlexey Budankov+class perf_event
48bd7c1c66SAlexey Budankov+{
49bd7c1c66SAlexey Budankov+	open
50bd7c1c66SAlexey Budankov+	cpu
51bd7c1c66SAlexey Budankov+	kernel
52bd7c1c66SAlexey Budankov+	tracepoint
53bd7c1c66SAlexey Budankov+	read
54bd7c1c66SAlexey Budankov+	write
55bd7c1c66SAlexey Budankov+}
56bd7c1c66SAlexey Budankov+
57bd7c1c66SAlexey Budankov+
58bd7c1c66SAlexey Budankovdiff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
59bd7c1c66SAlexey Budankov--- a/policy/flask/security_classes	2020-02-04 18:19:53.000000000 +0300
60bd7c1c66SAlexey Budankov+++ b/policy/flask/security_classes	2020-02-28 21:35:17.000000000 +0300
61bd7c1c66SAlexey Budankov@@ -200,4 +200,6 @@
62bd7c1c66SAlexey Budankov
63bd7c1c66SAlexey Budankov class xdp_socket
64bd7c1c66SAlexey Budankov
65bd7c1c66SAlexey Budankov+class perf_event
66bd7c1c66SAlexey Budankov+
67bd7c1c66SAlexey Budankov # FLASK
68bd7c1c66SAlexey Budankov
69bd7c1c66SAlexey Budankov4. Get into rpmbuild/SPECS directory and build policy packages from patched sources:
70bd7c1c66SAlexey Budankov
71bd7c1c66SAlexey Budankov   # rpmbuild --noclean --noprep -ba selinux-policy.spec
72bd7c1c66SAlexey Budankov
73bd7c1c66SAlexey Budankov   so you have this:
74bd7c1c66SAlexey Budankov
75bd7c1c66SAlexey Budankov   # ls -alh rpmbuild/RPMS/noarch/
76bd7c1c66SAlexey Budankov   total 33M
77bd7c1c66SAlexey Budankov   drwxr-xr-x. 2 root root 4.0K Mar 20 12:16 .
78bd7c1c66SAlexey Budankov   drwxr-xr-x. 3 root root 4.0K Mar 20 12:16 ..
79bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root 112K Mar 20 12:16 selinux-policy-3.14.4-48.fc31.noarch.rpm
80bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root 1.2M Mar 20 12:17 selinux-policy-devel-3.14.4-48.fc31.noarch.rpm
81bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root 2.3M Mar 20 12:17 selinux-policy-doc-3.14.4-48.fc31.noarch.rpm
82bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root  12M Mar 20 12:17 selinux-policy-minimum-3.14.4-48.fc31.noarch.rpm
83bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root 4.5M Mar 20 12:16 selinux-policy-mls-3.14.4-48.fc31.noarch.rpm
84bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root 111K Mar 20 12:16 selinux-policy-sandbox-3.14.4-48.fc31.noarch.rpm
85bd7c1c66SAlexey Budankov   -rw-r--r--. 1 root root  14M Mar 20 12:17 selinux-policy-targeted-3.14.4-48.fc31.noarch.rpm
86bd7c1c66SAlexey Budankov
87bd7c1c66SAlexey Budankov5. Install SELinux packages from Fedora repo, if not already done so, and
88bd7c1c66SAlexey Budankov   update with the patched rpms above:
89bd7c1c66SAlexey Budankov
90bd7c1c66SAlexey Budankov   # rpm -Uhv rpmbuild/RPMS/noarch/selinux-policy-*
91bd7c1c66SAlexey Budankov
92bd7c1c66SAlexey Budankov6. Enable SELinux Permissive mode for Targeted policy, if not already done so:
93bd7c1c66SAlexey Budankov
94bd7c1c66SAlexey Budankov   # cat /etc/selinux/config
95bd7c1c66SAlexey Budankov
96bd7c1c66SAlexey Budankov   # This file controls the state of SELinux on the system.
97bd7c1c66SAlexey Budankov   # SELINUX= can take one of these three values:
98bd7c1c66SAlexey Budankov   #     enforcing - SELinux security policy is enforced.
99bd7c1c66SAlexey Budankov   #     permissive - SELinux prints warnings instead of enforcing.
100bd7c1c66SAlexey Budankov   #     disabled - No SELinux policy is loaded.
101bd7c1c66SAlexey Budankov   SELINUX=permissive
102bd7c1c66SAlexey Budankov   # SELINUXTYPE= can take one of these three values:
103bd7c1c66SAlexey Budankov   #     targeted - Targeted processes are protected,
104bd7c1c66SAlexey Budankov   #     minimum - Modification of targeted policy. Only selected processes are protected.
105bd7c1c66SAlexey Budankov   #     mls - Multi Level Security protection.
106bd7c1c66SAlexey Budankov   SELINUXTYPE=targeted
107bd7c1c66SAlexey Budankov
108bd7c1c66SAlexey Budankov7. Enable filesystem SELinux labeling at the next reboot:
109bd7c1c66SAlexey Budankov
110bd7c1c66SAlexey Budankov   # touch /.autorelabel
111bd7c1c66SAlexey Budankov
112bd7c1c66SAlexey Budankov8. Reboot machine and it will label filesystems and load Targeted policy into the kernel;
113bd7c1c66SAlexey Budankov
114bd7c1c66SAlexey Budankov9. Login and check that dmesg output doesn't mention that perf_event class is unknown to SELinux subsystem;
115bd7c1c66SAlexey Budankov
116bd7c1c66SAlexey Budankov10. Check that SELinux is enabled and in Permissive mode
117bd7c1c66SAlexey Budankov
118bd7c1c66SAlexey Budankov    # getenforce
119bd7c1c66SAlexey Budankov    Permissive
120bd7c1c66SAlexey Budankov
121bd7c1c66SAlexey Budankov11. Turn SELinux into Enforcing mode:
122bd7c1c66SAlexey Budankov
123bd7c1c66SAlexey Budankov    # setenforce 1
124bd7c1c66SAlexey Budankov    # getenforce
125bd7c1c66SAlexey Budankov    Enforcing
126bd7c1c66SAlexey Budankov
127bd7c1c66SAlexey BudankovOpening access to perf_event_open() syscall on Fedora with SELinux
128bd7c1c66SAlexey Budankov==================================================================
129bd7c1c66SAlexey Budankov
130bd7c1c66SAlexey BudankovAccess to performance monitoring and observability operations by Perf
131bd7c1c66SAlexey Budankovcan be limited for superuser or CAP_PERFMON or CAP_SYS_ADMIN privileged
132bd7c1c66SAlexey Budankovprocesses. MAC policy settings (e.g. SELinux) can be loaded into the kernel
133bd7c1c66SAlexey Budankovand prevent unauthorized access to perf_event_open() syscall. In such case
134bd7c1c66SAlexey BudankovPerf tool provides a message similar to the one below:
135bd7c1c66SAlexey Budankov
136bd7c1c66SAlexey Budankov   # perf stat
137bd7c1c66SAlexey Budankov   Error:
138bd7c1c66SAlexey Budankov   Access to performance monitoring and observability operations is limited.
139bd7c1c66SAlexey Budankov   Enforced MAC policy settings (SELinux) can limit access to performance
140bd7c1c66SAlexey Budankov   monitoring and observability operations. Inspect system audit records for
141bd7c1c66SAlexey Budankov   more perf_event access control information and adjusting the policy.
142bd7c1c66SAlexey Budankov   Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
143bd7c1c66SAlexey Budankov   access to performance monitoring and observability operations for users
144bd7c1c66SAlexey Budankov   without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
145bd7c1c66SAlexey Budankov   perf_event_paranoid setting is -1:
146bd7c1c66SAlexey Budankov     -1: Allow use of (almost) all events by all users
147bd7c1c66SAlexey Budankov         Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
148bd7c1c66SAlexey Budankov   >= 0: Disallow raw and ftrace function tracepoint access
149bd7c1c66SAlexey Budankov   >= 1: Disallow CPU event access
150bd7c1c66SAlexey Budankov   >= 2: Disallow kernel profiling
151bd7c1c66SAlexey Budankov   To make the adjusted perf_event_paranoid setting permanent preserve it
152bd7c1c66SAlexey Budankov   in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
153bd7c1c66SAlexey Budankov
154bd7c1c66SAlexey BudankovTo make sure that access is limited by MAC policy settings inspect system
155bd7c1c66SAlexey Budankovaudit records using journalctl command or /var/log/audit/audit.log so the
156bd7c1c66SAlexey Budankovoutput would contain AVC denied records related to perf_event:
157bd7c1c66SAlexey Budankov
158bd7c1c66SAlexey Budankov   # journalctl --reverse --no-pager | grep perf_event
159bd7c1c66SAlexey Budankov
160bd7c1c66SAlexey Budankov   python3[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t.
161bd7c1c66SAlexey Budankov                                         If you believe that perf should be allowed open access on perf_event labeled unconfined_t by default.
162bd7c1c66SAlexey Budankov   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
163bd7c1c66SAlexey Budankov   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
164bd7c1c66SAlexey Budankov
165bd7c1c66SAlexey BudankovIn order to open access to perf_event_open() syscall MAC policy settings can
166bd7c1c66SAlexey Budankovrequire to be extended. On SELinux system this can be done by loading a special
167bd7c1c66SAlexey Budankovpolicy module extending base policy settings. Perf related policy module can
168bd7c1c66SAlexey Budankovbe generated using the system audit records about blocking perf_event access.
169bd7c1c66SAlexey BudankovRun the command below to generate my-perf.te policy extension file with
170bd7c1c66SAlexey Budankovperf_event related rules:
171bd7c1c66SAlexey Budankov
172bd7c1c66SAlexey Budankov   # ausearch -c 'perf' --raw | audit2allow -M my-perf && cat my-perf.te
173bd7c1c66SAlexey Budankov
174bd7c1c66SAlexey Budankov   module my-perf 1.0;
175bd7c1c66SAlexey Budankov
176bd7c1c66SAlexey Budankov   require {
177bd7c1c66SAlexey Budankov        type unconfined_t;
178bd7c1c66SAlexey Budankov        class perf_event { cpu kernel open read tracepoint write };
179bd7c1c66SAlexey Budankov   }
180bd7c1c66SAlexey Budankov
181bd7c1c66SAlexey Budankov   #============= unconfined_t ==============
182bd7c1c66SAlexey Budankov   allow unconfined_t self:perf_event { cpu kernel open read tracepoint write };
183bd7c1c66SAlexey Budankov
184bd7c1c66SAlexey BudankovNow compile, pack and load my-perf.pp extension module into the kernel:
185bd7c1c66SAlexey Budankov
186bd7c1c66SAlexey Budankov   # checkmodule -M -m -o my-perf.mod my-perf.te
187bd7c1c66SAlexey Budankov   # semodule_package -o my-perf.pp -m my-perf.mod
188bd7c1c66SAlexey Budankov   # semodule -X 300 -i my-perf.pp
189bd7c1c66SAlexey Budankov
190bd7c1c66SAlexey BudankovAfter all those taken steps above access to perf_event_open() syscall should
191bd7c1c66SAlexey Budankovnow be allowed by the policy settings. Check access running Perf like this:
192bd7c1c66SAlexey Budankov
193bd7c1c66SAlexey Budankov   # perf stat
194bd7c1c66SAlexey Budankov   ^C
195bd7c1c66SAlexey Budankov   Performance counter stats for 'system wide':
196bd7c1c66SAlexey Budankov
197bd7c1c66SAlexey Budankov         36,387.41 msec cpu-clock                 #    7.999 CPUs utilized
198bd7c1c66SAlexey Budankov             2,629      context-switches          #    0.072 K/sec
199bd7c1c66SAlexey Budankov                57      cpu-migrations            #    0.002 K/sec
200bd7c1c66SAlexey Budankov                 1      page-faults               #    0.000 K/sec
201bd7c1c66SAlexey Budankov       263,721,559      cycles                    #    0.007 GHz
202bd7c1c66SAlexey Budankov       175,746,713      instructions              #    0.67  insn per cycle
203bd7c1c66SAlexey Budankov        19,628,798      branches                  #    0.539 M/sec
204bd7c1c66SAlexey Budankov         1,259,201      branch-misses             #    6.42% of all branches
205bd7c1c66SAlexey Budankov
206bd7c1c66SAlexey Budankov       4.549061439 seconds time elapsed
207bd7c1c66SAlexey Budankov
208bd7c1c66SAlexey BudankovThe generated perf-event.pp related policy extension module can be removed
209bd7c1c66SAlexey Budankovfrom the kernel using this command:
210bd7c1c66SAlexey Budankov
211bd7c1c66SAlexey Budankov   # semodule -X 300 -r my-perf
212bd7c1c66SAlexey Budankov
213bd7c1c66SAlexey BudankovAlternatively the module can be temporarily disabled and enabled back using
214bd7c1c66SAlexey Budankovthese two commands:
215bd7c1c66SAlexey Budankov
216bd7c1c66SAlexey Budankov   # semodule -d my-perf
217bd7c1c66SAlexey Budankov   # semodule -e my-perf
218bd7c1c66SAlexey Budankov
219bd7c1c66SAlexey BudankovIf something went wrong
220bd7c1c66SAlexey Budankov=======================
221bd7c1c66SAlexey Budankov
222bd7c1c66SAlexey BudankovTo turn SELinux into Permissive mode:
223bd7c1c66SAlexey Budankov   # setenforce 0
224bd7c1c66SAlexey Budankov
225bd7c1c66SAlexey BudankovTo fully disable SELinux during kernel boot [3] set kernel command line parameter selinux=0
226bd7c1c66SAlexey Budankov
227bd7c1c66SAlexey BudankovTo remove SELinux labeling from local filesystems:
228bd7c1c66SAlexey Budankov   # find / -mount -print0 | xargs -0 setfattr -h -x security.selinux
229bd7c1c66SAlexey Budankov
230bd7c1c66SAlexey BudankovTo fully turn SELinux off a machine set SELINUX=disabled at /etc/selinux/config file and reboot;
231bd7c1c66SAlexey Budankov
232bd7c1c66SAlexey BudankovLinks
233bd7c1c66SAlexey Budankov=====
234bd7c1c66SAlexey Budankov
235bd7c1c66SAlexey Budankov[1] https://download-ib01.fedoraproject.org/pub/fedora/linux/updates/31/Everything/SRPMS/Packages/s/selinux-policy-3.14.4-49.fc31.src.rpm
236bd7c1c66SAlexey Budankov[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
237bd7c1c66SAlexey Budankov[3] https://danwalsh.livejournal.com/10972.html
238