aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/Documentation/security.txt
blob: 4fe3b8b1958f6da38d11fa2e43928f75aec8e290 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
Overview
========

For general security related questions of perf_event_open() syscall usage,
performance monitoring and observability operations by Perf see here:
https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html

Enabling LSM based mandatory access control (MAC) to perf_event_open() syscall
==============================================================================

LSM hooks for mandatory access control for perf_event_open() syscall can be
used starting from Linux v5.3. Below are the steps to extend Fedora (v31) with
Targeted policy with perf_event_open() access control capabilities:

1. Download selinux-policy SRPM package (e.g. selinux-policy-3.14.4-48.fc31.src.rpm on FC31)
   and install it so rpmbuild directory would exist in the current working directory:

   # rpm -Uhv selinux-policy-3.14.4-48.fc31.src.rpm

2. Get into rpmbuild/SPECS directory and unpack the source code:

   # rpmbuild -bp selinux-policy.spec

3. Place patch below at rpmbuild/BUILD/selinux-policy-b86eaaf4dbcf2d51dd4432df7185c0eaf3cbcc02
   directory and apply it:

   # patch -p1 < selinux-policy-perf-events-perfmon.patch
   patching file policy/flask/access_vectors
   patching file policy/flask/security_classes
   # cat selinux-policy-perf-events-perfmon.patch
diff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
--- a/policy/flask/access_vectors	2020-02-04 18:19:53.000000000 +0300
+++ b/policy/flask/access_vectors	2020-02-28 23:37:25.000000000 +0300
@@ -174,6 +174,7 @@
 	wake_alarm
 	block_suspend
 	audit_read
+	perfmon
 }
 
 #
@@ -1099,3 +1100,15 @@
 
 class xdp_socket
 inherits socket
+
+class perf_event
+{
+	open
+	cpu
+	kernel
+	tracepoint
+	read
+	write
+}
+
+
diff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
--- a/policy/flask/security_classes	2020-02-04 18:19:53.000000000 +0300
+++ b/policy/flask/security_classes	2020-02-28 21:35:17.000000000 +0300
@@ -200,4 +200,6 @@
 
 class xdp_socket
 
+class perf_event
+
 # FLASK

4. Get into rpmbuild/SPECS directory and build policy packages from patched sources:

   # rpmbuild --noclean --noprep -ba selinux-policy.spec

   so you have this:

   # ls -alh rpmbuild/RPMS/noarch/
   total 33M
   drwxr-xr-x. 2 root root 4.0K Mar 20 12:16 .
   drwxr-xr-x. 3 root root 4.0K Mar 20 12:16 ..
   -rw-r--r--. 1 root root 112K Mar 20 12:16 selinux-policy-3.14.4-48.fc31.noarch.rpm
   -rw-r--r--. 1 root root 1.2M Mar 20 12:17 selinux-policy-devel-3.14.4-48.fc31.noarch.rpm
   -rw-r--r--. 1 root root 2.3M Mar 20 12:17 selinux-policy-doc-3.14.4-48.fc31.noarch.rpm
   -rw-r--r--. 1 root root  12M Mar 20 12:17 selinux-policy-minimum-3.14.4-48.fc31.noarch.rpm
   -rw-r--r--. 1 root root 4.5M Mar 20 12:16 selinux-policy-mls-3.14.4-48.fc31.noarch.rpm
   -rw-r--r--. 1 root root 111K Mar 20 12:16 selinux-policy-sandbox-3.14.4-48.fc31.noarch.rpm
   -rw-r--r--. 1 root root  14M Mar 20 12:17 selinux-policy-targeted-3.14.4-48.fc31.noarch.rpm

5. Install SELinux packages from Fedora repo, if not already done so, and
   update with the patched rpms above:

   # rpm -Uhv rpmbuild/RPMS/noarch/selinux-policy-*

6. Enable SELinux Permissive mode for Targeted policy, if not already done so:

   # cat /etc/selinux/config

   # This file controls the state of SELinux on the system.
   # SELINUX= can take one of these three values:
   #     enforcing - SELinux security policy is enforced.
   #     permissive - SELinux prints warnings instead of enforcing.
   #     disabled - No SELinux policy is loaded.
   SELINUX=permissive
   # SELINUXTYPE= can take one of these three values:
   #     targeted - Targeted processes are protected,
   #     minimum - Modification of targeted policy. Only selected processes are protected.
   #     mls - Multi Level Security protection.
   SELINUXTYPE=targeted

7. Enable filesystem SELinux labeling at the next reboot:

   # touch /.autorelabel

8. Reboot machine and it will label filesystems and load Targeted policy into the kernel;

9. Login and check that dmesg output doesn't mention that perf_event class is unknown to SELinux subsystem;

10. Check that SELinux is enabled and in Permissive mode

    # getenforce
    Permissive

11. Turn SELinux into Enforcing mode:

    # setenforce 1
    # getenforce
    Enforcing

Opening access to perf_event_open() syscall on Fedora with SELinux
==================================================================

Access to performance monitoring and observability operations by Perf
can be limited for superuser or CAP_PERFMON or CAP_SYS_ADMIN privileged
processes. MAC policy settings (e.g. SELinux) can be loaded into the kernel
and prevent unauthorized access to perf_event_open() syscall. In such case
Perf tool provides a message similar to the one below:

   # perf stat
   Error:
   Access to performance monitoring and observability operations is limited.
   Enforced MAC policy settings (SELinux) can limit access to performance
   monitoring and observability operations. Inspect system audit records for
   more perf_event access control information and adjusting the policy.
   Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
   access to performance monitoring and observability operations for users
   without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
   perf_event_paranoid setting is -1:
     -1: Allow use of (almost) all events by all users
         Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
   >= 0: Disallow raw and ftrace function tracepoint access
   >= 1: Disallow CPU event access
   >= 2: Disallow kernel profiling
   To make the adjusted perf_event_paranoid setting permanent preserve it
   in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)

To make sure that access is limited by MAC policy settings inspect system
audit records using journalctl command or /var/log/audit/audit.log so the
output would contain AVC denied records related to perf_event:

   # journalctl --reverse --no-pager | grep perf_event

   python3[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t.
                                         If you believe that perf should be allowed open access on perf_event labeled unconfined_t by default.
   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
   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

In order to open access to perf_event_open() syscall MAC policy settings can
require to be extended. On SELinux system this can be done by loading a special
policy module extending base policy settings. Perf related policy module can
be generated using the system audit records about blocking perf_event access.
Run the command below to generate my-perf.te policy extension file with
perf_event related rules:

   # ausearch -c 'perf' --raw | audit2allow -M my-perf && cat my-perf.te

   module my-perf 1.0;

   require {
        type unconfined_t;
        class perf_event { cpu kernel open read tracepoint write };
   }

   #============= unconfined_t ==============
   allow unconfined_t self:perf_event { cpu kernel open read tracepoint write };

Now compile, pack and load my-perf.pp extension module into the kernel:

   # checkmodule -M -m -o my-perf.mod my-perf.te
   # semodule_package -o my-perf.pp -m my-perf.mod
   # semodule -X 300 -i my-perf.pp

After all those taken steps above access to perf_event_open() syscall should
now be allowed by the policy settings. Check access running Perf like this:

   # perf stat
   ^C
   Performance counter stats for 'system wide':

         36,387.41 msec cpu-clock                 #    7.999 CPUs utilized
             2,629      context-switches          #    0.072 K/sec
                57      cpu-migrations            #    0.002 K/sec
                 1      page-faults               #    0.000 K/sec
       263,721,559      cycles                    #    0.007 GHz
       175,746,713      instructions              #    0.67  insn per cycle
        19,628,798      branches                  #    0.539 M/sec
         1,259,201      branch-misses             #    6.42% of all branches

       4.549061439 seconds time elapsed

The generated perf-event.pp related policy extension module can be removed
from the kernel using this command:

   # semodule -X 300 -r my-perf

Alternatively the module can be temporarily disabled and enabled back using
these two commands:

   # semodule -d my-perf
   # semodule -e my-perf

If something went wrong
=======================

To turn SELinux into Permissive mode:
   # setenforce 0

To fully disable SELinux during kernel boot [3] set kernel command line parameter selinux=0

To remove SELinux labeling from local filesystems:
   # find / -mount -print0 | xargs -0 setfattr -h -x security.selinux

To fully turn SELinux off a machine set SELINUX=disabled at /etc/selinux/config file and reboot;

Links
=====

[1] https://download-ib01.fedoraproject.org/pub/fedora/linux/updates/31/Everything/SRPMS/Packages/s/selinux-policy-3.14.4-49.fc31.src.rpm
[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
[3] https://danwalsh.livejournal.com/10972.html