Jump to contentJump to page navigation: previous page [access key p]/next page [access key n]
documentation.suse.com / Troubleshooting SELinux

Troubleshooting SELinux

Publication Date: 05 Dec 2024
WHAT?

A system with SELinux in the enforcing mode may cause access denials that may prevent applications from running correctly. You can use audit2allow or setroubleshoot to analyze denial messages in a user-friendly way.

WHY?

This article provides instructions on how to solve access denials caused by SELinux without decreasing the security of your system.

EFFORT

It takes approximately 30 minutes to read the article.

GOAL

You will be able to use one of the further described tools to debug SELinux denials.

REQUIREMENTS
  • A running system with enabled SELinux.

1 The /var/log/audit/audit.log file

By default, if SELinux is the reason something is not working, a log message to this effect is sent to the /var/log/audit/audit.log file.

Note
Note: Empty /var/log/audit/audit.log

If you see an empty /var/log/audit/audit.log, it usually means that the auditd service is not running. In this case, proceed as follows:

  1. Start the auditd service:

    > sudo systemctl start auditd
  2. Enable the service in the targets of your system, using

    > sudo systemctl enable auditd

The /var/log/audit/audit.log file stores messages of access denials, service events and so on.

In Example 1: “Example lines from /etc/audit/audit.log, you can see a partial example of the contents of /var/log/audit/audit.log.

Example 1: Example lines from /etc/audit/audit.log
type=DAEMON_START msg=audit(1348173810.874:6248): auditd start, ver=1.7.7 format=raw kernel=3.0.13-0.27-default auid=0 pid=4235 subj=system_u:system_r:auditd_t res=success
type=AVC msg=audit(1348173901.081:292): avc:  denied  { write } for  pid=3426 comm="smartd" name="smartmontools" dev=sda6 ino=581743 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir
type=AVC msg=audit(1348173901.081:293): avc:  denied  { remove_name } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir
type=AVC msg=audit(1348173901.081:294): avc:  denied  { unlink } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:295): avc:  denied  { rename } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582373 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:296): avc:  denied  { add_name } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state~" scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=dir
type=AVC msg=audit(1348173901.081:297): avc:  denied  { create } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:298): avc:  denied  { write open } for  pid=3426 comm="smartd" name="smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.081:299): avc:  denied  { getattr } for  pid=3426 comm="smartd" path="/var/lib/smartmontools/smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file
type=AVC msg=audit(1348173901.309:300): avc:  denied  { append } for  pid=1316

A single message looks as follows:

  type=AVC msg=audit(1348173901.081:299): avc:  denied  { getattr } for  pid=3426 comm="smartd" path="/var/lib/smartmontools/smartd.WDC_WD2500BEKT_75PVMT0-WD_WXC1A21E0454.ata.state" dev=sda6 ino=582390 scontext=system_u:system_r:fsdaemon_t tcontext=system_u:object_r:var_lib_t tclass=file

Every line of the message can be broken down into sections. For example, the sections in the last line are:

type=AVC:

Every SELinux-related audit log line starts with the type identification, for example, type=AVC. Note that a message with the type=SYSCALL that follows one with a different type and has the same value of msg may provide further information regarding the event.

msg=audit(1348173901.309:300):

This is the time stamp, which is written in epoch time, the number of seconds that have passed since Jan 1, 1970. You can use date -d on the part up to the dot in the epoch time notation to find out when the event happened:

> date -d @1348173901
Thu Sep 20 16:45:01 EDT 2012
avc: denied { append }:

The specific action that was denied. In this case, the system has denied the appending of data to a file. While browsing through the audit log file, you can see other system actions, such as write open, getattr and more.

for pid=1316:

the process ID of the command or process that initiated the action

comm="rsyslogd":

the specific command that was associated with that PID

name="smartmontools":

the name of the subject of the action

dev=sda6 ino=582296:

the block device and inode number of the file that was involved

scontext=system_u:system_r:syslogd_t:

the source context, which is the context of the initiator of the action

tclass=file:

a class identification of the subject

2 Analyzing /var/log/audit/audit.log with audit2allow

Instead of interpreting the events in /var/log/audit/audit.log yourself, you can use the audit2allow command.

The command helps analyze the cryptic log messages in /var/log/audit/audit.log. An audit2allow troubleshooting session always consists of three different commands. First, you would use audit2allow -w -a to present the audit information in a more readable way. The audit2allow -w -a by default works on the audit.log file. If you want to analyze a specific message in the audit.log file, copy it to a temporary file and analyze the file with:

> sudo audit2allow -w -i FILENAME
Example 2: Analyzing audit messages
> sudo audit2allow -w -i testfile
type=AVC msg=audit(1348173901.309:300): avc:  denied  { append } for  pid=1316
comm="rsyslogd" name="acpid" dev=sda6 ino=582296
scontext=system_u:system_r:syslogd_t tcontext=system_u:object_r:apmd_log_t tclass=file
This was caused by:

A missing type enforcement (TE) allow rule.

To generate a loadable module to allow this access, run

> sudo audit2allow

To find out which specific rule has denied access, you can use audit2allow -a to show the enforcing rules from all events that were logged into the audit.log file, or audit2allow -i FILENAME to show it for messages that you have stored in a specific file:

Example 3: Viewing which lines deny access
> sudo audit2allow -i testfile
#============= syslogd_t ==============
allow syslogd_t apmd_log_t:file append;

To create an SELinux module with the name mymodule that you can load to allow the access that was previously denied, run

> sudo audit2allow -a -R -M mymodule

If you want to do this for all events that have been logged into the audit.log file, use the -a -M command arguments. To do it only for specific messages that are in a specific file, use -i -M as in the example below:

Example 4: Creating a policy module allowing an action previously denied
> sudo audit2allow -i testfile -M example
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i example.pp

As indicated by the audit2allow command, you can now run this module by using the semodule -i command, followed by the name of the module that audit2allow has created for you (example.pp in the above example).

3 Analyzing AVC messages using setroubleshoot

To analyze AVC denial messages in a user-friendly way, you can use the setroubleshoot tool.

3.1 Overview of setroubleshoot

3.1.1 What is setroubleshoot?

setroubleshoot is a tool that collects SELinux audit events from the kernel and analyses these events. If such an event occurs, setroubleshoot informs the administrator.

3.1.2 setroubleshoot components

The SELinux troubleshooting process involves the following components, all of which are installed on SUSE Linux Micro by default.

  • setroubleshoot-server provides the following tools:

    • setroubleshootd—the main daemon handling incoming requests and plug-in definitions. The daemon is activated on demand and does not require running via the systemd service. It can be managed only by a privileged user and a dedicated setroubleshoot user.

    • a database of alerts in the file /var/lib/setroubleshoot/setroubleshoot_database.xml

    • sealert—a command-line user interface to analyze the /var/log/audit.log

    • sedispatch—an audit dispatcher that scans SELinux AVC messages and transforms them into a DBus message, then passed to the daemon.

  • setroubleshoot-plugins—the plug-ins are used for AVC message analysis and provide suggestions on how to fix problems.

3.1.3 How does setroubleshoot work?

setroubleshoot comprises a daemon and analysis plug-ins. When a plug-in detects a problem, it is reported to the daemon, which then checks whether this is a known problem. If not, the new problem is added to the database along with a suggested solution.

3.1.4 Benefits of setroubleshoot

setroubleshoot provides the following functionalities to help you solve problems on your SELinux secured systems:

  • Sending alerts to the administrator when there is an AVC denial.

  • Automatic analysis of AVC denials.

  • Suggesting possible fixes, such as adjusting system configuration or installing updates and so on.

  • Browsing of previous alerts.

3.2 Configuring setroubleshoot

Even though the configuration of setroubleshoot does not require adjustment, you may face particular use cases when you need to change the defaults. The following sections provide the usual use cases.

The configuration file for setroubleshoot is /etc/setroubleshoot. Usually, you do not have to modify the configuration besides setting the e-mail notifications. However, if you need to change the configuration, you can either edit the file, or you can use the setroubleshootd command to configure a particular item. The command syntax is the following:

# setroubleshootd -c
SECTION.OPTION=VALUE

For example, to set the from_address option, run the command as follows:

#  setroubleshootd -c
email.from_address="example@mail.com"

3.2.1 Configuring setroubleshoot logging level

The default logging level (the value of sealert_log and setroubleshootd_log) is set to warning. However, you can set the value to one of the following:

critical

Only serious errors that prevent the system from functioning are logged.

error

Serious errors that may influence the system are reported.

warning

An indication that something unexpected happened, or that a problem might occur in the near future. However, the system works as expected.

info

A confirmation that the system is running correctly is logged.

debug

Detailed information for debugging purposes is logged.

3.2.2 Configuring setroubleshoot to send e-mail notifications

setroubleshoot can send you e-mail notifications if there is an AVC denial in the system.

To get these notifications, proceed as follows:

  1. Open the /etc/setroubleshoot/setroubleshoot.conf.

  2. In the file, adjust the following configuration items to suit your needs:

    smtp_host

    If the SMTP server does not run on the local host, fill in the server address.

    smtp_port

    The default is 25. Usually, this value does not require any adjustment.

    from_address

    Add the sender address.

    subject

    Configure a generic subject of all messages.

    recipients_filepath

    Specify the location of the notification recipients list.

    use_sendmail

    Set to true if you use SendMail.

  3. Create the mail recipients file on the path defined by the recipients_filepath option (/var/lib/setroubleshoot/email_alerts-recipients by default).

    Each e-mail address must be on a separate line. Comments are denoted with the # symbol.

3.2.3 Configuring the setroubleshoot database

You can change the amount of records in the setroubleshootd database, its location or the file name prefix.

database_dir

Specify an absolute path to the directory where the database XML file should reside.

filename

Configure a custom prefix of the database file name. The file name then looks as follows: FILENAME_PREFIX_database.xml.

max_alerts

Defines the maximum number of records in the database. Specify 0 for an unlimited number of records.

max_alert_age

Alerts older than the set limit are deleted from the database. You can use the units: year, month, day, hour, minute and second even in the plural form and you can use more than one unit, for example, 3 weeks 2 days, which equals to 23 days. If left empty, there is no limit.

3.2.4 Configure setroubleshoot to collect information from remote servers

You can configure setroubleshoot to gather SELinux audit data from remote servers. To do so, configure the address list.

[listen_for_client] address_list

On the server side.

[client_connect_to] address_list

On the client side.

Addresses on the list are in this format:

[{FAMILY}]ADDRESS[:PORT_NUMBER]

Where {FAMILY} is {inet} or {unix}%{path}s. If the address family is inet, you can optionally specify a port number, otherwise the port number is set to the default specified by the default_port configuration option. The default value {unix}%{path}s hostname means listening on the local Unix domain socket.

3.3 Running the /var/log/audit/audit.log analysis

To let the setroubleshoot tool analyze the audit log file, run the command:

> sudo sealert -a /var/log/audit/audit.log

In the following example output, there are two port values assigned to the SSHD service:

100% done
found 1 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------

SELinux is preventing sshd from name_bind access on the tcp_socket port 2222.

*****  Plugin bind_ports (92.2 confidence) suggests   ************************ 

If you want to allow sshd to bind to network port 2222
Then you need to modify the port type.
Do
# semanage port -a -t PORT_TYPE -p tcp 2222  1
    where PORT_TYPE is one of the following: ssh_port_t, vnc_port_t, xserver_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 sshd should be allowed name_bind access on the port 2222 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:
# ausearch -c 'sshd' --raw | audit2allow -M my-sshd
# semodule -X 300 -i my-sshd.pp

Additional Information:
...

First Seen                    2024-02-07 14:26:27 UTC
Last Seen                     2024-02-08 03:30:12 UTC
Local ID                      b5cbdd75-3f8d-425d-af75-f6cbf1540ffd 

Raw Audit Messages
type=AVC msg=audit(1707363012.797:25): avc:  denied  { name_bind } for  pid=841 comm="sshd" src=2222 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0


Hash: sshd,sshd_t,unreserved_port_t,tcp_socket,name_bind

1

The bind_ports plug-in provides the most suitable solution for the problem here.