Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf docs: Introduce security.txt file to document related issues

Publish instructions on how to apply LSM hooks for access control to
perf_event_open() syscall on Fedora distro with Targeted SELinux policy
and then manage access to the syscall.

Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: linux-security-module@vger.kernel.org
Cc: selinux@vger.kernel.org
Link: http://lore.kernel.org/lkml/290ded0a-c422-3749-5180-918fed1ee30f@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Alexey Budankov and committed by
Arnaldo Carvalho de Melo
bd7c1c66 c1034eb0

+237
+237
tools/perf/Documentation/security.txt
··· 1 + Overview 2 + ======== 3 + 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 7 + 8 + Enabling LSM based mandatory access control (MAC) to perf_event_open() syscall 9 + ============================================================================== 10 + 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: 14 + 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: 17 + 18 + # rpm -Uhv selinux-policy-3.14.4-48.fc31.src.rpm 19 + 20 + 2. Get into rpmbuild/SPECS directory and unpack the source code: 21 + 22 + # rpmbuild -bp selinux-policy.spec 23 + 24 + 3. Place patch below at rpmbuild/BUILD/selinux-policy-b86eaaf4dbcf2d51dd4432df7185c0eaf3cbcc02 25 + directory and apply it: 26 + 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 34 + @@ -174,6 +174,7 @@ 35 + wake_alarm 36 + block_suspend 37 + audit_read 38 + + perfmon 39 + } 40 + 41 + # 42 + @@ -1099,3 +1100,15 @@ 43 + 44 + class xdp_socket 45 + inherits socket 46 + + 47 + +class perf_event 48 + +{ 49 + + open 50 + + cpu 51 + + kernel 52 + + tracepoint 53 + + read 54 + + write 55 + +} 56 + + 57 + + 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 61 + @@ -200,4 +200,6 @@ 62 + 63 + class xdp_socket 64 + 65 + +class perf_event 66 + + 67 + # FLASK 68 + 69 + 4. Get into rpmbuild/SPECS directory and build policy packages from patched sources: 70 + 71 + # rpmbuild --noclean --noprep -ba selinux-policy.spec 72 + 73 + so you have this: 74 + 75 + # ls -alh rpmbuild/RPMS/noarch/ 76 + total 33M 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 86 + 87 + 5. Install SELinux packages from Fedora repo, if not already done so, and 88 + update with the patched rpms above: 89 + 90 + # rpm -Uhv rpmbuild/RPMS/noarch/selinux-policy-* 91 + 92 + 6. Enable SELinux Permissive mode for Targeted policy, if not already done so: 93 + 94 + # cat /etc/selinux/config 95 + 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. 101 + SELINUX=permissive 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. 106 + SELINUXTYPE=targeted 107 + 108 + 7. Enable filesystem SELinux labeling at the next reboot: 109 + 110 + # touch /.autorelabel 111 + 112 + 8. Reboot machine and it will label filesystems and load Targeted policy into the kernel; 113 + 114 + 9. Login and check that dmesg output doesn't mention that perf_event class is unknown to SELinux subsystem; 115 + 116 + 10. Check that SELinux is enabled and in Permissive mode 117 + 118 + # getenforce 119 + Permissive 120 + 121 + 11. Turn SELinux into Enforcing mode: 122 + 123 + # setenforce 1 124 + # getenforce 125 + Enforcing 126 + 127 + Opening access to perf_event_open() syscall on Fedora with SELinux 128 + ================================================================== 129 + 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: 135 + 136 + # perf stat 137 + Error: 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>) 153 + 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: 157 + 158 + # journalctl --reverse --no-pager | grep perf_event 159 + 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 164 + 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: 171 + 172 + # ausearch -c 'perf' --raw | audit2allow -M my-perf && cat my-perf.te 173 + 174 + module my-perf 1.0; 175 + 176 + require { 177 + type unconfined_t; 178 + class perf_event { cpu kernel open read tracepoint write }; 179 + } 180 + 181 + #============= unconfined_t ============== 182 + allow unconfined_t self:perf_event { cpu kernel open read tracepoint write }; 183 + 184 + Now compile, pack and load my-perf.pp extension module into the kernel: 185 + 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 189 + 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: 192 + 193 + # perf stat 194 + ^C 195 + Performance counter stats for 'system wide': 196 + 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 205 + 206 + 4.549061439 seconds time elapsed 207 + 208 + The generated perf-event.pp related policy extension module can be removed 209 + from the kernel using this command: 210 + 211 + # semodule -X 300 -r my-perf 212 + 213 + Alternatively the module can be temporarily disabled and enabled back using 214 + these two commands: 215 + 216 + # semodule -d my-perf 217 + # semodule -e my-perf 218 + 219 + If something went wrong 220 + ======================= 221 + 222 + To turn SELinux into Permissive mode: 223 + # setenforce 0 224 + 225 + To fully disable SELinux during kernel boot [3] set kernel command line parameter selinux=0 226 + 227 + To remove SELinux labeling from local filesystems: 228 + # find / -mount -print0 | xargs -0 setfattr -h -x security.selinux 229 + 230 + To fully turn SELinux off a machine set SELINUX=disabled at /etc/selinux/config file and reboot; 231 + 232 + Links 233 + ===== 234 + 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