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