Skip to main content

SELinux troubleshooting and pitfalls

SELinux can be challenging to troubleshoot, but by understanding the components of the service, you can handle whatever challenges it throws your way.
Image
SELinux troubleshooting and pitfalls
Image by MustangJoe from Pixabay

You can't let your failures define you. You have to let your failures teach you ― Barack Obama

One of the great battles, especially with third-party solution providers, is maintaining the security of our servers. In many cases, the challenge is the request to disable SELinux so that an application can run smoothly. Fortunately, that is occurring less and less.

In most of these cases, an analysis is enough to find the right troubleshooting or workaround.

SELinux is a labeling system, which tells us that each file, directory, or object in the system has a corresponding Label. Policies control the interaction between these elements. The kernel enforces these rules.

The two most important concepts are Labeling (files, processes, ports, etc.) and Type Enforcement (which isolates processes from each other according to their type).

The format used by the labels is: user:role:type:level (optional).

To find out the current configuration, run the getenforce and sestatus commands:

# getenforce
Enforcing
# 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:      32

Best practices tell us that when we are testing a new third-party application, we should temporarily configure SELinux in permissive mode in order to determine which policies or booleans (simple strings that change behavior) are necessary. Run the command:

# setenforce 0

Looking through the logs, you can find out what SELinux requires for the application to work properly.

What is SELinux trying to tell me?

There are only four main causes of errors that generate alerts in SELinux:

  1. Labeling.
  2. SELinux needs to know.
  3. SELinux policy and/or the application may have bugs.
  4. Your information may be compromised.

The last case is due to modifications made to attack vulnerabilities or avoid the tracking of activities, although in both cases, it is essential to review these alerts; for practical reasons, for the moment, we will not deal with them until a possible future posting.

Labeling

Labeling problem: Files in /srv/myweb are not properly labeled and cannot be accessed.

SELinux assigns a label for each element involved in the same service:

  • Binary file: /usr/sbin/httpd → httpd_exec_t
  • Configuration file: /etc/httpd → httpd_config_t
  • Log file: /var/log/httpd → httpd_log_t
  • Content Directory: /var/www/html → httpd_sys_content_t
  • Startup Script: /usr/lib/systemd/system/httpd.service → httpd_unit_file_t
  • Process: /usr/sbin/httpd → httpd_t
  • Ports: 80/tcp, 443/tcp → httpd_t and httpd_port_t

On the web server, a process running in the httpd_t context can only interact with objects with the httpd_something_t label.

Solution: Correctly labeling the files.

If you know the correct label, then run :

# semanage fcontext -a -t httpd_sys_content_t '/srv/myweb(/.*)?'

If you know a file with the equivalent label, then run:

# semanage fcontext -a -e /srv/myweb /var/www

Restore the default context of the files, for both cases:

# restorecon -vR /srv/myweb

Labeling problem: If a file is moved, instead of being copied, it keeps its original label.

$ mv index.html /var/www/html/

Solution: Correctly labeling the file.

Change the context to the correct label:

# chcon -t httpd_system_content_t /var/www/html/index.html

Changing the context with a reference label:

# chcon --reference /var/www/html/ /var/www/html/index.html

Restore the default context of the file, for both cases:

# restorecon -vR /var/www/html/

[ You might also like: Accessing SELinux policy documentation ]

SELinux needs to know

Service customization: The web server will listen for requests on port 8585.

To add the desired port to the context, run:

# semanage port -a -t http_port_t -p tcp 8585

Adding features to the service: The web server will be able to send emails.

To enable the mail sending function, turn on the boolean, running:

# setsebool -P httpd_can_sendmail 1

The -P flag makes the change permanent in the boolean.

To get all the booleans, run:

# getsebool -a

To check the status of a boolean, run:

# semanage boolean -l

Policies troubleshooting

Some services do not have a specific policy created containing the sufficient permissions needed to work with SELinux. To determine what these permissions are, it is necessary to set the permissive mode and inspect the logs for access errors.

Service not working: wicd is used instead of NetworkManager service to handle wireless connections.

Inspecting the audit.log file for denied access:

# grep denied audit.log | cut -d{ -f2 | sort -n | uniq -u
 create } for  pid=2670 comm="wicd" scontext=system_u:system_r:NetworkManager_t:s0 tcontext=system_u:system_r:NetworkManager_t:s0 tclass=appletalk_socket permissive=1
 create } for  pid=2670 comm="wicd" scontext=system_u:system_r:NetworkManager_t:s0 tcontext=system_u:system_r:NetworkManager_t:s0 tclass=ax25_socket permissive=1
 ioctl } for  pid=2670 comm="wicd" path="socket:[52681]" dev="sockfs" ino=52681 ioctlcmd=0x8b01 scontext=system_u:system_r:NetworkManager_t:s0 tcontext=system_u:system_r:NetworkManager_t:s0 tclass=ax25_socket permissive=1
 ioctl } for  pid=2670 comm="wicd" path="socket:[52684]" dev="sockfs" ino=52684 ioctlcmd=0x8b01 scontext=system_u:system_r:NetworkManager_t:s0 tcontext=system_u:system_r:NetworkManager_t:s0 tclass=appletalk_socket permissive=1
 setattr } for  pid=2214 comm="wicd" name="dhclient.conf.template" dev="dm-0" ino=437068 scontext=system_u:system_r:NetworkManager_t:s0 tcontext=unconfined_u:object_r:etc_t:s0 tclass=file permissive=0

Note that some elements involved in the contexts NetworkManager_t and etc_t require rights and access to different files and sockets creation.

Create the type enforcement (.te) file with the necessary permissions for the policy:

# vi my_wicd.te
module my_wicd 1.0;
 
require {
        type NetworkManager_t;
        type etc_t;
        class ipx_socket create;
        class ax25_socket { create ioctl };
        class appletalk_socket { create ioctl };
        class file setattr;
}
 
#============= NetworkManager_t ==============
allow NetworkManager_t etc_t:file setattr;
allow NetworkManager_t self:appletalk_socket { create ioctl };
allow NetworkManager_t self:ax25_socket { create ioctl };
allow NetworkManager_t self:ipx_socket create;

To compile the policy, install the package selinux-policy-devel and generate the policy package:

# make -f /usr/share/selinux/devel/Makefile my_wicd.pp

To activate the newly-generated module, run:

# semodule -i my_wicd.pp

Policy error message: Trying to access my website, I find SELinux errors in the logs.

One of the common pitfalls in troubleshooting SELinux error messages is creating policies according to all the error messages found. In most cases, if the setroubleshoot package is installed, the same alert will give us all possible workaround options, from best to least.

To review the setroubleshoot alerts generated today, run:

# journalctl -t setroubleshoot --since today
Dec 08 13:08:33 lab.example.com setroubleshoot[12013]: failed to retrieve rpm info for /var/www/html/index.html
Dec 08 13:08:34 lab.example.com setroubleshoot[12013]: SELinux is preventing /usr/sbin/httpd from getattr access on the file /var/www/html/index.html. For complete SELinux messages run: sealert -l 011df984-4eb6-4079-98ab-cba173c4342e
Dec 08 13:08:34 lab.example.com setroubleshoot[12013]: SELinux is preventing /usr/sbin/httpd from getattr access on the file /var/www/html/index.html.
                                                               
 *****  Plugin restorecon (99.5 confidence) suggests   ************************
                                                               
 If you want to fix the label
 /var/www/html/index.html default label should be httpd_sys_content_t.
 Then you can run restorecon. The access attempt may have been stopped due to insufficient permissions to access a parent directory, in which case try to change the following command accordingly.
 Do
 # /sbin/restorecon -v /var/www/html/index.html
                                                               
 *****  Plugin catchall (1.49 confidence) suggests   **************************
                                                               
 If you believe that httpd should be allowed getattr access on the index.html 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 'httpd' --raw | audit2allow -M my-httpd
 # semodule -X 300 -i my-httpd.pp

In this case, the best possible solution is simply to fix the file's label.

[ Improve your skills managing and using SELinux with this helpful guide. ] 

Wrap up

SELinux can be challenging to troubleshoot, but by applying the concepts noted here and understanding the components of the service, you can handle whatever challenges it throws your way.

Remember:

Image
Image of a label stating: SELINUX IS A LABELING SYSTEM
Topics:   Linux   Linux administration   Security  
Author’s photo

Alex Callejas

Alex Callejas is a Services Content Architect of Red Hat, based in Mexico City and an Enable Sysadmin contributor. With more than 20 years of experience as Sysadmin, he has strong expertise on infrastructure hardening and automation. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.