SELinux Cheat Sheet
Reading SELinux status
Command | Description | Examples |
---|---|---|
cat /etc/selinux/config | Get SELinux boot configuration | # 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. # See also: # https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/using_selinux/changing-selinux-states-and-modes_using-selinux#changing-selinux-modes-at-boot-time_changing-selinux-states-and-modes # # NOTE: Up to RHEL 8 release included, SELINUX=disabled would also # fully disable SELinux during boot. If you need a system with SELinux # fully disabled instead of SELinux running with no policy loaded, you # need to pass selinux=0 to the kernel command line. You can use grubby # to persistently set the bootloader to boot with selinux=0: # # grubby --update-kernel ALL --args selinux=0 # # To revert back to SELinux enabled: # # grubby --update-kernel ALL --remove-args selinux # SELINUX=enforcing # 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 |
cat /proc/cmdline | Check if SELinux is disabled on boot | # cat /proc/cmdline BOOT_IMAGE=(hd0,gpt3)/vmlinuz-5.14.0-427.26.1.el9_4.x86_64 root=UUID=aec1c1e8-3576-4eb2-ab62-f62984e655a2 console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M selinux=0 |
getenforce | Get current enforcement status | # getenforce Enforcing |
sestatus | Get current SELinux status | # sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: targeted Current mode: enforcing Mode from config file: enforcing Policy MLS status: enabled Policy deny_unknown status: allowed Memory protection checking: actual (secure) Max kernel policy version: 33 |
Enabling / disabling SELinux
Command | Description | Examples |
---|---|---|
setenforce | Set current enforcement status | # setenforce Enforcing |
grubby --update-kernel ALL --args selinux=0 | Disable SELinux permanently starting with next boot | |
grubby --update-kernel ALL --remove-args selinux | Enable SELinux permanently starting with next boot (if if was disabled) |
Finding SELinux violations
Command | Description | Examples |
---|---|---|
journalctl -t setroubleshoot | Get journal logs for SELinux issues | Jul 19 07:09:41 rhel9-training setroubleshoot[47738]: SELinux is preventing /usr/lib/systemd/systemd from execute access on the file cause-violation. For co> Jul 19 07:09:41 rhel9-training setroubleshoot[47738]: SELinux is preventing /usr/lib/systemd/systemd from execute access on the file cause-violation. * Plugin catchall (100. confidence) suggests ****** If you believe that systemd should be allowed execute access on the cause-violation file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c '(iolation)' --raw |
grep denied /var/log/audit/audit.log | Print raw SELinux denials | # grep denied /var/log/audit/audit.log<br >type=AVC msg=audit(1703120795.400:102): avc: denied { execute } for pid=1586 comm="(iolation)" name="cause-violation" dev="vda4" ino=58946753 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=0 |
ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent | Find recent denials | # ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent ---- time->Fri Jul 19 07:29:17 2024 type=PROCTITLE msg=audit(1721388557.563:621): proctitle="(iolation)" type=SYSCALL msg=audit(1721388557.563:621): arch=c000003e syscall=21 success=no exit=-13 a0=7fff382a8ae0 a1=1 a2=0 a3=3 items=0 ppid=1 pid=47806 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="(iolation)" exe="/usr/lib/systemd/systemd" subj=system_u:system_r:init_t:s0 key=(null) type=AVC msg=audit(1721388557.563:621): avc: denied { execute } for pid=47806 comm="(iolation)" name="cause-violation" dev="vda4" ino=58946753 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=0 |
ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts today | Find denials for today | # ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts today ---- time->Fri Jul 19 07:29:17 2024 type=PROCTITLE msg=audit(1721388557.563:621): proctitle="(iolation)" type=SYSCALL msg=audit(1721388557.563:621): arch=c000003e syscall=21 success=no exit=-13 a0=7fff382a8ae0 a1=1 a2=0 a3=3 items=0 ppid=1 pid=47806 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="(iolation)" exe="/usr/lib/systemd/systemd" subj=system_u:system_r:init_t:s0 key=(null) type=AVC msg=audit(1721388557.563:621): avc: denied { execute } for pid=47806 comm="(iolation)" name="cause-violation" dev="vda4" ino=58946753 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=0 |
sealert -l "*" | sealert -a /var/log/audit/audit.log | setroubleshoot client tool |
Listing SELinux labels
Command | Description | Examples |
---|---|---|
seinfo -b | List all available SELinux booleans | |
seinfo -r | List all available SELinux rules | |
seinfo -t | List all available SELinux types | |
seinfo -u | List all available SELinux users |
Process operations
Command | Description | Examples |
---|---|---|
ps aux -Z | List all processes and the SELinux label that they run with | |
ps -fZ --pid $(pgrep -f |
Show the current label of a process | # ps -fZ --pid $(pgrep -f open-messages) LABEL UID PID PPID C STIME TTY TIME CMD system_u:system_r:unconfined_service_t:s0 root 2236 1 0 08:43 ? 00:00:00 python /opt/tutorial/bin/open-messages |
File operations
Command | Description | Examples |
---|---|---|
ls -al -Z | List all files in this directory and their SELinux label | |
chron -R -t tmp_t /test | Change SELinux type temporarily for the directory, recursively | |
restorecon -v -R /test | Reset labels to default recursively in this directory | |
touch /.autorelabel | Force an auto relabel on system boot | |
semanage fcontext -l | List default label configuration for the entire system | |
semanage fcontext -C -l | List all local customizations to label configuration | # semanage fcontext -C -l SELinux fcontext type Context /opt/tutorial/bin/cause-violation all files system_u:object_r:httpd_sys_content_t:s0 |
semanage fcontext -a -t etc_t '/test(/.*)?' | Configure default label for a directory | |
semanage fcontext -d '/test(/.*)?' | Delete default label configuration for a directory |
SELinux booleans
Command | Description | Examples |
---|---|---|
getsebool -a | List all SELinux booleans (effective state) | |
getsebool httpd_use_nfs | List a specific SELinux boolean (effective state) | |
semanage boolean -l | List all SELinux booleans (effective and permanent) | |
cat /sys/fs/selinux/booleans/httpd_use_nfs | Query effective and permanent state of single variable from /sys | # cat /sys/fs/selinux/booleans/httpd_use_nfs 1 1 |
setsebool httpd_use_nfs on | Set SELinux boolean temporarily | |
semanage boolean -m --on httpd_use_nfs | Set SELinux boolean permanently (effective on next reboot) |
SELinux ports
Command | Description | Examples |
---|---|---|
semanage port -l | List all port mappings (type label to allowed port) | # semanage port -l |
semanage port -a -t http_port_t -p tcp 3333 | Allow an SELinux type to use a specific port |
Creating custom SELinux types and policies
Custom service
We will create a custom SELinux type and policies for the following service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 2 3 4 5 6 7 8 9 |
|
Creating a custom SELinux type
Create a policy for the executable:
1 2 3 4 5 6 7 8 |
|
By default, the new policy will be permissive, meaning that issues will be logged but not enforced:
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 |
|
Remove the permissive line from open_messages.te
to enforce rules:
1 |
|
Rebuild the synstem policy with the new configuration (make sure to check the output as this may fail with missing dependencies):
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 |
|
Verify that the executable now is labeled with the new custom type:
1 2 |
|
Creating policies for the custom type
Rerun the service, but with permissive rules:
1 2 |
|
Restart the service and make sure that it's running:
1 2 |
|
Generate the list of rules needed to make the service run:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Copy the list of rules from the output and append them to open_messages.te:
1 2 3 4 5 6 7 8 9 10 |
|
And enforce SELinux again for the policy and rebuild the policies:
1 2 |
|
Empty /var/log/audit/audit.log:
1 |
|
Start the open-messages service and make sure that it's running correctly:
1 2 |
|
Inspect the service, you will see that it runs with the new label:
1 2 3 |
|
Check that there are no SELinux denied messages for open-messages:
1 |
|
Disabling a custom SELinux policy
List the open_messages SELinux module:
1 2 |
|
Disable the open_messages SELinux module (you can use -e to re-enable):
1 |
|
List the module again:
1 2 |
|
Run restorecon to restore the SELinux context of the binary and list the labels after the relabel:
1 2 3 4 |
|
Re-enable the module with:
1 |
|
And verify:
1 2 |
|
Run restorecon to restore the SELinux context of the binary and list the labels after the relabel:
1 2 3 4 |
|
Removing a custom SELinux policy
List the open_messages SELinux module:
1 2 |
|
Remove the open_messages SELinux module:
1 2 |
|
List the module again:
1 2 |
|
Run restorecon to restore the SELinux context of the binary and list the labels after the relabel:
1 2 3 4 |
|