Find out if (and how) SELinux is enabled:
Disable SELinux (set it to permissive):
Re-enable SELinux with the following command:
Starting with CentOS 5, many SELinux problems can be fixed by simply changing booleans. If you see error messages flooding your audit logs, google for them. You may find out that booleans may be helpful. There is often no need to build selinux modules.
A list of available SELinux booleans can be generated:
Search for something specific, e.g. httpd:
getsebool -a | grep httpd
Change a boolean temporarily, then try if you experience the same problem again:
setsebool httpd_can_network_connect on
If you are sure this fixed your problems, set it permanent so it will resist reboots:
setsebool -P httpd_can_network_connect on
Sometimes, we wanna change default ports, e.g. let's change SSH port 22 to port 222. Let's just write the entire procedure down here because you wanna change this anyway. Let's assume you're running CentOS 6/7 or Fedora 24/25:
See a list of ports allowed by SELinux:
yum -y install policycoreutils-python semanage port -l
Without firewalld, insert the following line in /etc/sysconfig/iptables where your other INPUT accept lines reside:
-A INPUT -p tcp -m state --state NEW -m tcp --dport 222 -j ACCEPT
Then restart iptables:
service iptables restart
With firewalld installed, you can use commands to do this:
firewall-cmd --permanent --zone=public --add-port=222/tcp firewall-cmd --reload
Now we will install the policycoreutils and manage SELinux accordingly:
yum -y install policycoreutils-python semanage port -a -t ssh_port_t -p tcp 222
Last but not least, edit /etc/ssh/sshd.config and find the line that says:
Change it to:
then restart SSH by typing:
service sshd restart
All processes and files have a SELinux security context. You can list them with the -Z switch, this works with many utilities. Sometimes you will need specific directories to have a different security context from the defaults because e.g. your webserver needs to write to an uncommon directory. This is best done with semanage fcontext, which is a better approach than creating an selinux module.
ls -alZ /bin/bash -rwxr-xr-x. 1 root root system_u:object_r:shell_exec_t:s0 1072008 30. Sep 10:25 /bin/bash
ps -auxZ | grep bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 15278 0.0 0.2 122920 4456 pts/0 Ss 18:19 0:00 -bash
Shit often fucks up because a user moved some modified files instead of copying them. If they would copy, the copy would adapt to the destination's security context. But when moving them, the source security context is used and then everything's fucked. Restore the location's context:
# restorecon -v /var/www/html/index.html
This also works recursively:
# restorecon -Rv /var/www/html
List configured security contexts:
semanage fcontext -l
Change the security context of a directory, this example will allow nginx to write to a php session directory:
semanage fcontext -a -t httpd_sys_rw_content_t '/var/lib/php/session(/.*)?'
Delete a changed security context of a directory:
semanage fcontext -d -t httpd_sys_rw_content_t '/var/lib/php/session(/.*)?'
Please remember to restorecon the affected directory after having made changes to security contexts.
The 'chcon' command may be used to change SELinux security context of a file or files/directories in a similar way to how 'chown' or 'chmod' may be used to change the ownership or standard file permissions of a file.
Using Apache as an example, suppose you want to change the DocumentRoot to serve web pages from a location other than the default /var/www/html/ directory. Assume we create a directory (or maybe a mount point) at /html/ and create an index.html file there:
# mkdir /html # touch /html/index.html # ls -Z /html/index.html -rw-r--r-- root root user_u:object_r:default_t /html/index.html # ls -Z | grep html drwxr-xr-x root root user_u:object_r:default_t html
We see that both the directory /html/ and file /html/index.html have the security context type: default_t. If we start our web browser and try to view the page, SELinux will properly deny access and log the error because the directory and file(s) have the wrong security context. We need to set the correct security context type for Apache of: httpd_sys_content_t.
# chcon -v --type=httpd_sys_content_t /html context of /html changed to user_u:object_r:httpd_sys_content_t # chcon -v --type=httpd_sys_content_t /html/index.html context of /html/index.html changed to user_u:object_r:httpd_sys_content_t # ls -Z /html/index.html -rw-r--r-- root root user_u:object_r:httpd_sys_content_t /html/index.html # ls -Z | grep html drwxr-xr-x root root user_u:object_r:httpd_sys_content_t html
Equally we could have set both in one go using the -R recursive switch:
# chcon -Rv --type=httpd_sys_content_t /html
Modifying security contexts in this manner will persist between system reboots but only until the modified portion of the filesystem is relabeled. This is a not uncommon operation and the proper solution, after testing, is to write a local custom rule (a so-called Policy Module) and merge it into the base local rules. This will be an additional rule on top of the 200+ rules already present. To make the security context changes permanent, even through a complete filesystem relabel, we can use the SELinux Management Tool or the 'semanage' command from the command line:
semanage fcontext -a -t httpd_sys_content_t "/html(/.*)?"
to add a file context of type httpd_sys_content_t for everything under /html.1)
If you think that SELinux is blocking your operations, find the cause:
a) You may already be audit logging. If you're not auditlogging already, start fresh:
rm -rf /var/log/audit/* ; semodule -B -D ; setenforce 0 ; service auditd restart
b) Now trigger the same problem again and afterwards filter the relevant AVC deny lines into a text file
cat /var/log/audit/audit.log | grep "AVC" > /tmp/whatever.log
c) check /tmp/whatever.log and remove all shit that doesnt belong to the problem
d) Create a policy module with a module name that you will remember:
cat /tmp/whatever.log | audit2allow -M your-fucking-modulename
e) For major enlightement and also some generated tips and advises, check the text version of your module:
f) Install the generated module
semodule -i your-fucking-modulename.pp
g) If shit now works, make sure to set selinux back to normal shit:
setenforce 1 ; semodule --build
You are able to view all installed semodules. If you were clever enough to name your own modules with e.g. your preceding nickname, then you will be able to find your custom modules quickly:
To delete a semodule, issue the following command:
semodule -r <modulename>
Sometimes, when you really fucked up (e.g. with SELinux permanently disabled you upgraded security contexts or did a dist-upgrade or wildly moved system files from one system to the other) stuff is really messed up. Solution: Relabel the entire fucking shit. Remember it will take ages so get two coffees.
Relabel on reboot:
touch /.autorelabel reboot
If this doesn't work because you did a kick-ass dist-upgrade and then re-enabled SELinux, try issueing another command first:
genhomedircon touch /.autorelabel reboot
On Fedora 30, this can be easily accomplished like this: