SELinux server management
SELinux is an implementation of the FLASK security model, and can be used on most recent RHEL and Fedora Core versions. It provides Über powerful access control. Machine can still be pwned with a kernel exploit though
Contents
Running
You have three options for the state of SELinux on the server, and two options for the type of policy enforced:
- State:
(recommended) enforcing - runs SELinux logging and enforcing the active policy
permissive (default) - runs SELinux but only logs policy breaches, does not enforce them
disabled - does not run SELinux at all from init. Switching away from disabled requires the filesystems to be relabelled on next bootup.
- Policy:
(recommended) targeted - only contains policies that affect system and daemons
- strict - policies affect entire system, daemons, filesystem, network etc. More complicated.
To see the current status of the server, run the command:
sestatus -v
State and policy can be configured at install or by editing /etc/selinux/config.
To switch between enforcing/permissive and disabled, the system will need to relabel all files and this will require a reboot.
To switch between permissive and enforcing use the setenforce command:
setenforce [ Enforcing | Permissive | 1 | 0 ]
There are also a bunch of useful things in /selinux (similar to /proc) that can be used.
Troubleshooting
If you have the system in the enforcing state, it will actively enforce the current policy (i.e. only after standard Linux permission checks pass, SELinux will then either allow or deny the access).
To find out if SELinux is denying access, check out:
/var/log/audit/audit.log, if auditd is running, otherwise:
dmesg output, or /var/log/messages
and have a look for entries containing avc (Access Vector Cache) and denied. It is possible (but rare) for a policy to specify that an access is to be denied without an audit record being generated. If you suspect that this is the case you should test the system by switching the system to permissive mode as documented above and performing your tests and then setting the system back to enforcing mode.
SELinux will fail to work correctly either because of:
- Incorrect file/directory security context labeling;
- The policy needs adjusting.
File and directory security contexts
Every object (file/directory/socket/etc) on the system has a security context attribute. You can use the -Z switch to ls to display the security context for an object (similarly the -Z switch to ps will display the type (called the domain) for a process). For example:
[root@dreadnought lib]# ls -Z drwxr-xr-x root root system_u:object_r:rpm_var_lib_t alternatives drwxr-xr-x amanda disk system_u:object_r:var_lib_t amanda drwx------ apache apache system_u:object_r:var_lib_t dav drwxr-xr-x root root system_u:object_r:dhcp_state_t dhcp drwxr-x--- root root system_u:object_r:var_lib_t dhcpv6 drwxr-xr-x root root system_u:object_r:var_lib_t games drwxr-xr-x root root system_u:object_r:httpd_sys_content_t htdig -rw-r--r-- root root system_u:object_r:var_lib_t logrotate.status drwxr-xr-x root root system_u:object_r:var_lib_t misc drwxr-xr-x mysql mysql system_u:object_r:mysqld_db_t mysql drwxr-x--- root root root:object_r:var_lib_t mysqlbackup drwxr-xr-x root root system_u:object_r:var_lib_nfs_t nfs drwxr-xr-x ntp ntp system_u:object_r:ntp_drift_t ntp drwx------ osiris osiris system_u:object_r:var_lib_t osiris drwx-----x postgres postgres system_u:object_r:postgresql_db_t pgsql drwxr-xr-x root root system_u:object_r:var_lib_t php -rw------- root root user_u:object_r:var_lib_t random-seed drwxr-xr-x rpm rpm system_u:object_r:rpm_var_lib_t rpm drwxr-x--- root slocate system_u:object_r:var_lib_t slocate -rw-r--r-- root root system_u:object_r:var_lib_t supportinfo drwxr-xr-x root root system_u:object_r:var_lib_t tomcat5 drwxr-xr-x root root system_u:object_r:var_lib_t up2date drwxr-xr-x webalize root system_u:object_r:var_lib_t webalizer
These security contexts are persistently stored in the filesystem using extended attributes. They are an attribute of the object (inode) and not dependent on its path/name.
In the above output the directory alternatives has a security context of system_u:object_r:rpm_var_lib_t. This is read as:
User of system_u
Role of object_r
Type of rpm_var_lib_t
Under SELinux with the targeted policy you can ignore everything except the Type.
When a file/directory (or any other object) is created, its security context will be copied from its environment (i.e for a file/directory its security context will be copied from the directory in which it was created). Utilities that are SELinux aware and move a file should preserve the security context. Utilities that are SELinux aware and copy a file will only preserve the security context if they are told to preserve permissions. Unfortunately this means that there is the possibility of a file having an incorrect security context resulting in the security policy not acting as expected.
After reading the avc denied message and finding out which operation was being attempted on which particular file/directory you then need to figure out if the denial was due to the security context being incorrect. How can you determine what the correct context should be ? Luckily the security policy has a database of default security contexts based on a path regular expression. The easiest way to check if the type is incorrect is to run fixfiles.
fixfiles check PATH
This will tell you if the security context of PATH is not equal to the default and not one of the customisable types listed in /etc/selinux/targeted/contexts/customizable_types. If the security context is set to one of the customisable types and you want to find out what the default security context should be then you can either use the matchpathcon utility, run semanage fcontext -l, or consult the policy values in /etc/selinux/targeted/contexts/files/. If you have files installed in an unusual location you should change the default file security context (see below).
If you determine there really are discrepancies, you should reset the security context to the default by using:
fixfiles relabel PATH
You can also use the restorecon utility.
You can use the chcon command to manually set the security context on the file or directory:
chcon -R system_u:object_r:mysqld_db_t mysql
It behaves like chown or chmod in most respects. Try to start the daemon again, and if there are any more avc denied messages, repeat the process iteratively until the daemon starts and there are no more avc denied messages.
NB: Our use of bind mounts can cause files in /data to be mislabelled. It is best to run fixfiles on individual directory structures and ignore /data
Changing the default security context of a file/directory
If the policy has an incorrect default security context for a file/directory you should change the defaults so that fixfiles or restorecon don't complain. First you need to determine what the security context should be. You can probably figure it out from seeing what the default security context is for a file in the default location. Otherwise you can have a read through /etc/selinux/targeted/src/policy/file_contexts/program (you will need the policy source installed).
semanage can be used to adjust the default file contexts for a file:
[root@galleon files]# matchpathcon /crap /crap system_u:object_r:default_t [root@galleon files]# semanage fcontext -a -t home_root_t '/crap' [root@galleon files]# matchpathcon /crap /crap system_u:object_r:home_root_t
There are also defaults made for home directories in /etc/selinux/targeted/contexts/files/file_contexts.homedirs . This file is generated by running genhomedircon based on /etc/selinux/targeted/contexts/files/homedir_template (entries are only made for user account with a different home directory to /home).
Automatic relabeling
restorecond can be used to magically set the security context of a new file to the default. See the man page for restorecond and restorecon for details.
Tuning the policy
Some parts of the policy are controlled by booleans. Changing a boolean is a quick and proper way of fixing some problems that you may encounter.
To get a list of booleans that you can change:
getsebool -a
To change a particular boolean:
setsebool -P BOOLEAN {true|false}The -P flag to setsebool makes the change persistent.
Changing the policies
Extension |
File type |
Notes |
.te |
Type enforcement |
See http://www.nsa.gov/selinux/papers/policy2/t1.html for details |
.fc |
File contexts |
Default file contexts |
.mod |
Policy module |
Binary of compiled type enforcment policy |
.pp |
Policy package |
The module and optional additonal files (contexts, users, etc) |
In order to change the customise the running policy you can either:
(Recommended) Generate a module policy and load the new module. The selinux sources are not required. This can be done via new versions of audit2allow
$ cat /var/log/audit/audit.log | audit2allow -M local Generating type enforcment file: local.te Compiling policy: checkmodule -M -m -o local.mod local.te Building package: semodule_package -o local.pp -m local.mod ******************** IMPORTANT *********************** In order to load this newly created policy package into the kernel, you are required to execute semodule -i local.pp $ semodule -i local.pp
The policy module will be stored in /etc/selinux/targeted/modules/active/modules and should still work after reboots. It can also be done manually
$ cat /var/log/audit/audit.log | audit2allow -m local > local.te $ cat local.te module local 1.0; require { role system_r; class fifo_file { getattr ioctl }; type cupsd_config_t; type unconfined_t; }; allow cupsd_config_t unconfined_t:fifo_file { getattr ioctl }; <review local.te and customize as desired> Building module policy manually # Compile the module $ checkmodule -M -m -o local.mod local.te # Create the package $ semodule_package -o local.pp -m local.mod # Load the module into the kernel $ semodule -i local.ppGenerate a new monolithic policy: You will need to load the selinux sources, e.g. selinux-policy-targeted-sources (or selinux-policy-devel). This allows you to make changes, roll them out and activate the new policy straight away. They will be located in /etc/selinux/targeted/src. The audit2allow program reads the dmesg output and creates exceptions for any avc denied messages it finds. It can be run without any parameters, but it is best if you copy and paste the few entries into a temporary file and run audit2allow over it:
cd /etc/selinux/targeted/src/policy/domains/misc/ less /var/log/messages vi temp audit2allow -i temp -o local.te
The local.te file will be integrated into the policy when you build it:
cd /etc/selinux/targeted/src/policy make make load
The new customised policy will now be active. Try to start the daemon, and again follow an iterative process to eliminate deny messages. Customising the running policy should only be used as a last resort measure, it is not a good idea generally to create a lot of policy exceptions.
Handling AVC denials efficiently
In future you will be able to rapidly fix problems with the power of the SELinux troubleshooting tool. Stay tuned.
man audit2why
Integration with cfengine
- Cfengine:
- Automatically sets the mode to enforcing
Sets defaults to targeted/enforcing in /etc/selinux/config
Rolls out a makefile to /etc/selinux/anchor that is capable of compiling and installing new policy
Rolls out any TE policy files from cfinputs/$(host)/etc/selinux/anchor
Calls the makefile to install the policy customisations any time files are updated in /etc/selinux/anchor
- Additions to the local policy files rolled out by cfengine need to be made manually in the cfengine-stored file.
The machine must be made a member of SELINUX_SERVICABLE for any of these changes to be made.
Shared Hosting security assumptions
Content is in ~/public_html/
CGIs are in ~/public_html/cgi-bin/
- CGIs and PHP will read arbitrary files
- New files uploaded via FTP/SSH need to be correctly labelled and working
Automatically restored security contexts
The default contexts below are
Object |
Default type |
Notes |
File ~/.htpasswd |
httpd_sys_htaccess_t |
|
Files matching ~/public_html/*.cgi |
httpd_unconfined_script_exec_t |
|
Files in ~/public_html/cgi-bin/ |
httpd_unconfined_script_exec_t |
Directories can't be exec_t otherwise suexec won't work. You will get errors like cannot get docroot information |
Files under ~/public_html/ that match .ht.* |
httpd_sys_htaccess_t |
|
Anything else in ~/public_html/ |
httpd_sys_content_t |
httpd_user_content_t is an alias for this type |
Example paths for testing:
/home/putz/.htpasswd /home/putz/public_html/ /home/putz/public_html/.htaccess /home/putz/public_html/index.html /home/putz/public_html/index.cgi /home/putz/public_html/blarg/ /home/putz/public_html/blarg/.htaccess /home/putz/public_html/blarg/index.html /home/putz/public_html/blarg/index.cgi /home/putz/public_html/cgi-bin/ /home/putz/public_html/cgi-bin/.htaccess /home/putz/public_html/cgi-bin/binary /home/putz/public_html/cgi-bin/blarg/ /home/putz/public_html/cgi-bin/blarg/.htaccess /home/putz/public_html/cgi-bin/blarg/binary
Uploading new PHP content via FTP/SSH |
Works... |
Uploading new static content via FTP/SSH |
Works... |
Uploading new CGIs via FTP/SSH |
Works... |
Misc
Vim syntax highlighting
Download http://www.cip.ifi.lmu.de/~bleher/selinux/te.vim into ~/.vim/syntax/ and then add to ~/.vim/filetype.vim
augroup filetypedetect
au! BufRead,BufNewFile *.te setfiletype te
augroup END
Further documentation
If you can't find what you are looking for on this page, try:
Try running man -k selinux
rpm -ql setools
rpm -ql policycoreutils
https://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/selinux-guide/
SELinux by Example: Using Security Enhanced Linux in Safari bookshelf
- IRC: #selinux on irc.freenode.net
Info about restorecond: http://danwalsh.livejournal.com/4368.html