## Introduction to SELinux concepts w/pictures - [Your visual how-to guide for SELinux policy enforcement](https://opensource.com/business/13/11/selinux-policy-guide) - [The SELinux Coloring Book](http://people.redhat.com/duffy/selinux/selinux-coloring-book_A4-Stapled.pdf) ## RHEL 7 SELinux User's & Administrator's Guide This is great. You should read at least the 1st and 10th chapter of it. - [Introductory Chapter 1](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/chap-Security-Enhanced_Linux-Introduction.html) (short link: bit.ly/selinux-guide-rhel7) - [⁠1.1. Benefits of running SELinux](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/chap-Security-Enhanced_Linux-Introduction.html#sect-Security-Enhanced_Linux-Introduction-Benefits_of_running_SELinux) - [1.2. Examples](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Introduction-Examples.html) - [1.3. SELinux Architecture](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Introduction-SELinux_Architecture.html) - [1.4. SELinux States and Modes](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Introduction-SELinux_Modes.html) - [1.5. What Is New in Red Hat Enterprise Linux 7](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sec-What-is-new-in-RHEL-7.html) - [Troubleshooting Chapter 10](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/chap-Security-Enhanced_Linux-Troubleshooting.html) (short link: bit.ly/selinux-guide-rhel7-troubleshooting) - [10.1. What Happens when Access is Denied](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/chap-Security-Enhanced_Linux-Troubleshooting.html#sect-Security-Enhanced_Linux-Troubleshooting-What_Happens_when_Access_is_Denied) - [10.2. Top Three Causes of Problems](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Top_Three_Causes_of_Problems.html) - [⁠10.3. Fixing Problems](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html) - [10.3.1. Linux Permissions](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Linux_Permissions) - [10.3.2. Possible Causes of Silent Denials](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Possible_Causes_of_Silent_Denials) - [10.3.3. Manual Pages for Services](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Manual_Pages_for_Services) - [10.3.4. Permissive Domains](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Permissive_Domains) - [10.3.5. Searching For and Viewing Denials](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Searching_For_and_Viewing_Denials) - [10.3.6. Raw Audit Messages](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Raw_Audit_Messages) - [10.3.7. sealert Messages](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-sealert_Messages) - [10.3.8. Allowing Access: audit2allow](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Allowing_Access_audit2allow) ## Targeted KCS Solutions Solutions to specific problems. - [How to add custom SELinux filename transition rules in RHEL7](https://access.redhat.com/solutions/2220381) - [How to create SELinux dontaudit rules to hide avc denied warnings](https://access.redhat.com/solutions/1523643) - [Is there a way to copy the entire SELinux config between machines?](https://access.redhat.com/solutions/108443) ## Man pages - See [Guide: 10.3.3. Manual Pages for Services](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Manual_Pages_for_Services) - Most useful are `man -k semanage` - Additional man pages like `httpd_selinux` not installed by default but are available in the **selinux-policy-doc** package ``` yum install selinux-policy-doc mandb &>/dev/null man -k _selinux ``` Note that prior to RHEL 7.3, the man pages were in the **selinux-policy-devel** package ``` yum install selinux-policy-devel mandb &>/dev/null man -k _selinux ``` ## Checking enforcing/permissive/disabled status SELinux can be globally disabled via `/etc/default/selinux` or the kernel cmdline, requiring a reboot. SELinux can be put into permissive mode in the same way, but that can also be done on the fly without a reboot. - See [Guide: 1.4. SELinux States and Modes](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Introduction-SELinux_Modes.html) - Commands to check status: ``` sestatus # Show current & config-file status getenforce # Show current status grep ^SELINUX= /etc/selinux/config # Show config-file (permanent) status grep -e enforcing= -e selinux= /etc/default/grub /etc/grub2.cfg # Check for kernel args ``` ## Permissive domains Instead of using `setenforce 0` on the whole system when you suspect a problem, switch a particular process domain into permissive mode. - See `man semanage-permissive` and [⁠Guide: 10.3.4. Permissive Domains](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Permissive_Domains) - Immediately & permanently switch a process domain into permissive mode ``` semanage permissive --add logrotate_t semanage permissive -a httpd_t ``` - Immediately & permanently switch a permissive domain back to enforcing ``` semanage permissive --del logrotate_t semanage permissive -d httpd_t ``` - Check for permissive domains ``` semodule -l | grep permissive ``` - Immediately disable all permissive domains (i.e., switch them back to enforcing) ``` semodule -d permissivedomains ``` - Immediately enable any previously-set permissive domains (i.e., switch them back to permissive) ``` semodule -e permissivedomains ``` ## File labels Every file gets a label. Policy determines what a process domain can do to files of each label. - See `man semanage-fcontext` and [Guide: ⁠10.2.1. Labeling Problems](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Top_Three_Causes_of_Problems.html#sect-Security-Enhanced_Linux-Top_Three_Causes_of_Problems-Labeling_Problems) - Set a file type on a directory ``` semanage fcontext --add samba_share_t "/path/to/dir(/.*)?" && restorecon -RF /path/to/dir semanage fcontext -a httpd_sys_content_t "/path(/.*)?" && restorecon -RF /path ``` - Create an alternate location (equivalency rule) based on an existing directory (which is useful because it recursively includes rules) ``` semanage fcontext -a -e /var/www /web && restorecon -RF /web semanage fcontext -a -e /home /our/home && restorecon -RF /our/home ``` - Check what a particular [source] process domain can do to a particular [target] file type ``` sesearch -CA -s httpd_t -t var_log_t ``` ## Network port labels Policy must explicitly allow confined services specific access to certain network port labels; however, the labels can be changed just as easily as file labels. - See `man semanage-port` and [Guide: 10.2.2. How are Confined Services Running?](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Top_Three_Causes_of_Problems.html#sect-Security-Enhanced_Linux-Top_Three_Causes_of_Problems-How_are_Confined_Services_Running) - Check for port labels for a particular domain/service ``` semanage port -l | grep http # Look for http-labeled ports semanage port -l | grep ssh # Look for ssh-labeled ports semanage port -l | grep 3333 # Look for a specific port man httpd_selinux man sshd_selinux sesearch -CA -s httpd_t -c tcp_socket -p name_bind # Look for tcp port types that a particular domain is allowed to bind to ``` - Permanently set labels on network ports ``` semanage port -a -t http_port_t -p tcp 3333 # Permanently add a label to a specific port semanage port -a -t ssh_port_t -p tcp 2222 ``` ## Boolean on/off switches There are many commonly-used configurations that require opening up the default SELinux policy a little, e.g.: allowing webservers to send email or read content from NFS. This can always be done by flipping simple toggles. - See `man semanage-boolean` and [Guide: 10.2.2. How are Confined Services Running?](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Top_Three_Causes_of_Problems.html#sect-Security-Enhanced_Linux-Top_Three_Causes_of_Problems-How_are_Confined_Services_Running) - Check for booleans for a particular domain ``` semanage boolean -l | grep httpd man httpd_selinux ``` - Set booleans ``` setsebool httpd_can_sendmail on # Immediate & temporary setsebool -P httpd_use_nfs on # Permanent & takes a minute to rebuild policy setsebool -P httpd_builtin_scripting=off httpd_tmp_exec=1 # "on" and "1", "off" and "0" all work; equals sign optional unless trying to do multiple booleans at once ``` ## Inspect audit AVC records All SELinux AVC denials get logged by the kernel to audit (assuming `auditd` is running) and thus show up in `/var/log/audit/audit.log` by default. These can be inspected directly or with `ausearch` & `aureport`. - See `man ausearch` and `man aureport` and [Guide: 10.3.5. Searching For and Viewing Denials](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Searching_For_and_Viewing_Denials) and [Guide: 10.3.6. Raw Audit Messages](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Raw_Audit_Messages) - Use `aureport` to get a broad overview ``` aureport -a # Get a report of all AVC denial events aureport -i -a | awk 'NR==4 || NR>5' | column -t # Interpret syscall numbers to names; show in columnized list ``` - Use `ausearch` to drill down ``` ausearch -i -m avc # Show all from standard audit.log files ausearch -i -m avc -ts recent # Show last 10 minutes ausearch -i -m avc -ts today -c httpd # Show particular command since midnight ausearch -i -m avc -ts 16:05 -su httpd_t # Show particular source (subject) SELinux context since 16:05 PM ``` ## Leverage setroubleshoot to get recommendations There's an optional `setroubleshoot-server` package that will automatically translate audit AVC records into more human-readable syslog messages with actionable recommendations. - See `man sealert` and [Guide: ⁠10.3.7. sealert Messages](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-sealert_Messages) - Example usage 1. Install and enable ``` yum install setroubleshoot-server service auditd restart ``` 1. Note that there's a bug in the `setroubleshoot` packages shipped with RHEL 7.2 and older which makes the sealert command somewhat unusable. Update to the latest version. (See: [sealert (from setroubleshoot-server) in RHEL 7 fails with error: failed to connect to server: No such file or directory](https://access.redhat.com/solutions/2529361)) 1. Do something that SELinux denies and watch the journal (or `/var/log/messages`) for the logs, e.g.: ``` ~]# yum install httpd ... ~]# echo Listen 18888 >/etc/httpd/conf.d/listen18888.conf ~]# systemctl restart httpd Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details. ~]# journalctl _COMM=setroubleshootd -- Logs begin at Tue 2016-08-16 00:28:39 EDT, end at Tue 2016-08-16 00:30:02 EDT. -- Aug 16 00:30:02 a72.example.com setroubleshoot[1463]: SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 18888. For complete SELinux messages. run sealert -l 87fea572-9f35-47cc-8c81-eb9e9ae8cad0 Aug 16 00:30:02 a72.example.com python[1463]: SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 18888. ***** Plugin bind_ports (92.2 confidence) suggests ************************ If you want to allow /usr/sbin/httpd to bind to network port 18888 Then you need to modify the port type. Do # semanage port -a -t PORT_TYPE -p tcp 18888 where PORT_TYPE is one of the following: http_cache_port_t, http_port_t, jboss_management_port_t, jboss_messaging_port_t, ntop_port_t, puppet_port_t. ***** Plugin catchall_boolean (7.83 confidence) suggests ****************** If you want to allow nis to enabled Then you must tell SELinux about this by enabling the 'nis_enabled' boolean. Do setsebool -P nis_enabled 1 ***** Plugin catchall (1.41 confidence) suggests ************************** If you believe that httpd should be allowed name_bind access on the port 18888 tcp_socket 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: # grep httpd /var/log/audit/audit.log | audit2allow -M mypol # semodule -i mypol.pp ``` 1. Instead of using `journalctl`, you could of course also do something like ... ``` grep sealert /var/log/messages ``` 1. Execute the suggested `sealert` command to view full details, e.g., from above ``` sealert -l 87fea572-9f35-47cc-8c81-eb9e9ae8cad0 ``` - Another possibility is to use `sealert` to analyze a file, getting recommendations for all AVCs in it (could be any audit.log file from any system) ``` sealert -a /var/log/audit/audit.log | less -S ``` ## Confining users In the standard targeted policy, all users are unconfined; however, you can easily change that. You can start simple with preset users but of course you can get as granular as you want. - See `man semanage-login` and `man semanage-user` and [Guide: ⁠3.3. Confined and Unconfined Users](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Targeted_Policy-Confined_and_Unconfined_Users.html) and [Guide: 6. Confining Users](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/chap-Security-Enhanced_Linux-Confining_Users.html) - Create a new user that is mapped to `guest_u` (i.e., no internet, no sudo/su or most other setuid/setgid apps, no X) ``` useradd -Z guest_u newuserbob ``` - Make it so `guest_u` & `xguest_u` won't be allowed to execute anything in `/tmp` or `$HOME` ``` ~]# setsebool -P guest_exec_content=off xguest_exec_content=off ~]# semanage boolean -l | grep exec_content auditadm_exec_content (on , on) Allow auditadm to exec content guest_exec_content (off , off) Allow guest to exec content dbadm_exec_content (on , on) Allow dbadm to exec content xguest_exec_content (off , off) Allow xguest to exec content secadm_exec_content (on , on) Allow secadm to exec content logadm_exec_content (on , on) Allow logadm to exec content user_exec_content (on , on) Allow user to exec content staff_exec_content (on , on) Allow staff to exec content sysadm_exec_content (on , on) Allow sysadm to exec content ``` - Confine an existing user, mapping to `user_u` (i.e., no su/sudo or most other setuid/setgid apps) ``` semanage login -a -s user_u existinguseralice ``` ## Fix SELinux denials by allowing requested access This should be a *last* resort ... done sparingly & with care. The vast majority of problems can be solved by setting proper file labels or tweaking booleans or figuring out that the application/admin is doing something wrong. - See `man audit2allow` and [Guide: 10.3.8. Allowing Access: audit2allow](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html#sect-Security-Enhanced_Linux-Fixing_Problems-Allowing_Access_audit2allow) - Example: ``` ausearch -i -m avc | grep xxxx | audit2allow ```