SELinux writes log entries that enable system administrators to monitor its operation. The following subsections explain the format of SELinux log messages, some logging subtleties, and how to use the Audit2allow utility to automatically generate rules to allow operations logged as denied.
When a program attempts an operation that is checked by the SELinux security engine, SELinux may make a log entry. As more fully explained in Chapter 2, operations that are denied generally cause a log entry to be made, whereas permitted operations generally do not. However, SELinux policy rules can override this principle.
Apart from the timestamp and other information that accompanies every system log message, SELinux log messages have the following general format:
avc:result
{operation
} for pid=pid
exe=exe
path=opath
dev=devno
:ptno
ino=node
scontext=source
tcontext=target
tclass=class
A given SELinux log message may omit one or more of the attribute-value pairs given in the general format. Log messages include only the applicable attribute-value pairs.
The variable fields within the log message have the following meanings:
result
The value granted
or denied
,
indicating whether SELinux permitted or prohibited the operation.
operation
The operation that was attempted, such as read
or
write
. SELinux defines about 150 operations.
Appendix B summarizes the SELinux operations that can appear in log
messages.
pid
The process ID of the process that attempted the operation.
exe
The absolute path of the text file (executable) associated with the process that attempted the operation.
path
The absolute path of the object on which the operation was attempted.
devno
The block device number associated with the object on which the operation was attempted.
ptno
The partition number associated with the object on which the operation was attempted.
node
The inode number of the object on which the operation was attempted.
source
The security context of the process that attempted the operation.
target
The security context of the target object.
class
The type of the target object, such as file
.
Appendix A summarizes the SELinux object classes.
Let’s parse a typical log message, which follows:
avc: denied { write } for pid=10400 exe=/usr/bin/nmap lport=255 scontext=root:staff_r:nmap_t tcontext=root:staff_r:nmap_t tclass=rawip_socket
This message indicates that a write
operation was
denied. The process that attempted the operation,
/usr/bin/nmap
, had process ID
10400
. The security context of the process was
root:staff_r:nmap_t
and the security context of
the object was root:staff_r:nmap_t
. The target
object class was rawip_socket
. In addition, the
message indicates the logical (source) port which was requested,
255
. So, the messages tells us that the security
engine has prevented Nmap from writing to a socket.
Let’s now parse a log message that presents a common complication:
avc: denied { read } for pid=12999 exe=/usr/bin/slocate name=slocate.db dev=03:02 ino=391745 scontext=bill:staff_r:staff_t tcontext=system_u:object_r:var_lib_t tclass=file
This message indicates that a read
operation was
denied. The process that attempted the operation,
/usr/bin/slocate
, had process ID
12999
.
When the object path appears in the log message, we immediately know the identity of the object. However, SELinux often does not include the object path. In such cases, we must determine the object’s identity from the information that is available. In this example, we have the device, partition, and inode numbers. We’ll identify the object by using these.
The log entry shows that the process attempted to access partition 2
of block device 3. If Linux kernel sources are installed, we can
determine the identity of this device by searching the file
/usr/src/linux/Documentation/devices.txt
, which
indicates that block device 3 is associated with
/dev/hda
. We can verify this result by issuing
the ls command:
# ls -l /dev/hda
brw-rw---- 1 root disk 3, 0 Oct 4 2003 /dev/hda
If the devices.txt
file is not available, we can
search the /dev
directory for a device having
the indicated device number.
To determine the partition related to the log message, we can use the df command:
# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda1 102454 13311 83853 14% /boot
/dev/hda2 3854576 2930172 728600 81% /
/dev/hda4 73854600 65026572 5076380 93% /space
none 63272 0 63272 0% /dev/shm
From the command output, we learn that partition 2,
/dev/hda2
, is associated with the root
filesystem, /
.
Skipping several intervening attribute-value pairs to which
we’ll return in a moment, we learn from the
tclass
attribute that the object in question has
type file
. To determine the path associated with
the file
object, we can use the
-inum option of the find
command, which searches for a node having the specified inode number.
The following command searches the filesystem mounted at
/
for a node having inode number 391745:
# find / -inum 391745 /var/lib/slocate/slocate.db
The file
object is identified as the file
/var/lib/slocate/slocate.db
, which is not
surprising in view of /usr/bin/slocate
being the
process that attempted the read
operation.
Inodes can be deleted and reused. So, if enough system activity has occurred between generation of a log entry and an attempt to identify the referenced object by its inode number, the attempt is likely to fail or turn up an incorrect path.
Returning now to the attribute-value pairs we skipped,
scontext
and tcontext
, we can
infer the reason that led to denial of the operation. As indicated by
the value of the scontext
attribute, the
slocate
process was running in the security
context bill:staff_r:staff_t
. Apparently, this
context is not permitted to perform the read
operation on file
objects having the type
indicated by the value of the tcontext
attribute,
system_u:object_r:var_lib_t
. The most likely cause
is that the slocate
process should have been run
in some other context, such
as sysadm_t
.
To avoid excessive overhead, SELinux attempts to curtail unnecessary logging. To do so, it uses separate strategies for permissive and enforcing mode.
In permissive mode, SELinux attempts to log each denial only once, avoiding a flood of identical and therefore redundant messages. To do so, SELinux maintains a cache of log entries. Before making a log entry, SELinux checks whether the entry resides in the cache. If so, SELinux suppresses the log entry.
Under some circumstances, this caching behavior may become confusing to a system administrator, who wonders why a denied operation is not accompanied by a log entry. This is particularly likely if a long interval passes between the original denial that resulted in a cache entry and subsequent denials. If you suspect that you’re confronted with such a situation, you can prompt SELinux to clear its cache of log entries. You can do so either of two ways:
Change to the policy source directory and reload the security policy:
cd /etc/security/selinux/src/policy make reload
Toggle between modes. For instance, in Fedora Core, you can issue the commands:
setenforce 1 setenforce 0
In enforcing mode
(1)
,
SELinux limits the rate at which log
entries are made. This is necessary because some programs
don’t properly check error return codes. So, when
SELinux prohibits an operation, these programs could cause large
numbers of repeated log entries if SELinux didn’t
have limits on logging.
When rate limiting is occurring, log entries are lost. Obviously, this can complicate diagnosis and troubleshooting. Unfortunately, SELinux does not provide system administrators with a means of controlling its rate-limiting functionality. Nor does SELinux provide a log entry informing a system administrator that a rate limit has been initiated or terminated. Consequently, system administrators should bear in mind the possibility that SELinux log entries may be missing during intervals of high activity. Eventually, SELinux developers hope to stop depending on the system logging facility by implementing a separate logging facility designed expressly for SELinux.
SELinux includes a special utility, Audit2allow, that scans the system log,
looking for entries pertaining to denied operations and generating a
file of allow
rules that—if added to the
security policy—would prevent those operations from being
denied. Using the utility is a nontrivial matter, because the rules
it generates are not always optimal. To ensure proper security,
it’s often necessary to define new domains or make
other structural changes rather than blindly add the generated rules
to the security policy. Chapter 9 gives tips
and procedures for using the Audit2allow
utility.