At this point in the development of SELinux, it’s common for policies to contain small bugs that cause operations to fail when applications or programs are used in unusual ways unanticipated by policy developers. As an SELinux administrator, one of the most frequent SELinux policy customizations you’re likely to perform is adding permissions to coax the security engine into accepting an operation. Let’s consider an actual situation based on Fedora Core 2’s SELinux implementation and see how it’s resolved. The procedure we’ll follow isn’t the only procedure or best procedure. Creating new policies typically entails a generous dollop of troubleshooting, which tends to be relatively unstructured. So rather than see our procedure as the universal norm, you should see it as merely an illustrative example.
Though unfamiliar to many, the Nmap program is a popular tool among those concerned with security that provides many useful functions. For instance, using Nmap, you can determine the ports on which a network host is listening and what service is running on each open port.
Suppose you install and run Nmap and obtain the following error message:
# nmap -sT 127.0.0.1
Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 17:23 UTC
Unable to find nmap-services! Resorting to /etc/services
It seems that Nmap is unable to read the
nmap-services
file.
Checking the system log, you find that SELinux recently logged eight
denial messages:
avc: denied { read } for pid=8682 exe=/usr/bin/nmap name=urandom dev=dm-0 ino=306563 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:urandom_ device_t tclass=chr_file avc: denied { read } for pid=8682 exe=/usr/bin/nmap name=random dev=dm-0 ino=301298 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:random_ device_t tclass=chr_file avc: denied { read } for pid=8682 exe=/usr/bin/nmap name=urandom dev=dm-0 ino=306563 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:urandom_ device_t tclass=chr_file avc: denied { read } for pid=8682 exe=/usr/bin/nmap name=random dev=dm-0 ino=301298 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:random_ device_t tclass=chr_file avc: denied { read } for pid=8682 exe=/usr/bin/nmap name=localtime dev=dm-0 ino=32810 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:locale_t tclass=file avc: denied { search } for pid=8682 exe=/usr/bin/nmap name=root dev=dm-0 ino=262145 scontext=root:sysadm_r:traceroute_t tcontext=root:object_r:staff_home_dir_ t tclass=dir avc: denied { read } for pid=8682 exe=/usr/bin/nmap name=nmap-services dev=dm-4 ino=231156 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:usr_t tclass=file avc: denied { search } for pid=8682 exe=/usr/bin/nmap name=policy dev=dm-0 ino=49161 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:policy_src_t tclass=dir
Notice that Nmap runs in the domain
traceroute_t
; we’ll use that
information later. For now, focus on the seventh message, which is
next to last. This message shows that the security engine denied read
access to the nmap-services
file. However, the
message gives only the base filename, not the full path. You can find
the location of the file by using the locate
command:
# locate nmap-services
/usr/share/nmap/nmap-services
Next, double check the security context of the file:
# ls -Z /usr/share/nmap
-rw-r--r-- root root system_u:object_r:usr_t nmap-os-fingerprints
-rw-r--r-- root root system_u:object_r:usr_t nmap-protocols
-rw-r--r--+ root root system_u:object_r:usr_t nmap-rpc
-rw-r--r-- root root system_u:object_r:usr_t nmap-service-probes
-rw-r--r-- root root system_u:object_r:usr_t nmap-services
The security context, system_u:object_r:usr_t
,
agrees with that shown in the log message. Apparently, the
traceroute_t
domain does not have permission to
read files in the security context
system_u:object_r:usr_t
, including the
nmap-services
file.
Now that we understand the problem, let’s fix it. We
could give the traceroute_t
domain read access to
the system_u:object_r:usr_t
security context by
adding the following declaration to the SELinux policy:
allow traceroute_t usr_t:file { read };
However, adding this declaration would enable access to files other
than nmap-services
and might compromise system
security. We need a more focused fix.
Let’s examine the FC file for the
traceroute_t
domain, file_contexts/program/traceroute.fc
:
# traceroute
/bin/traceroute.* -- system_u:object_r:traceroute_exec_t
/usr/(s)?bin/traceroute.* -- system_u:object_r:traceroute_exec_t
/usr/bin/lft -- system_u:object_r:traceroute_exec_t
/usr/bin/nmap -- system_u:object_r:traceroute_exec_t
Notice that the only security context referenced in the FC file is
system_u:object_r:traceroute_exec_t
. This context
is used to label the Nmap executable and other executable files. So,
it doesn’t seem to be an appropriate security
context for the nmap-services
file. However, it
does seem appropriate to label the file with a security context based
on the domain type traceroute_t
.
Let’s add the following line to the FC file:
/usr/share/nmap.* system_u:object_r:traceroute_t
This line should cause the /usr/share/nmap
directory and the files it contains to be labeled with the security
context system_u:object_r:traceroute_t
. To
relabel the directory, issue the
commands:
#make load
#setfiles file_contexts/file_contexts /usr/share/nmap
Next, double check the result of the relabeling, which turned out okay:
# ls -Z /usr/share/nmap
-rw-r--r-- root root system_u:object_r:traceroute_t nmap-os-fingerprints
-rw-r--r-- root root system_u:object_r:traceroute_t nmap-protocols
-rw-r--r--+ root root system_u:object_r:traceroute_t nmap-rpc
-rw-r--r-- root root system_u:object_r:traceroute_t nmap-service-probes
-rw-r--r-- root root system_u:object_r:traceroute_t nmap-services
Now, retry the command:
# nmap -sT 127.0.0.1
Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 17:46 UTC
Unable to find nmap-services! Resorting to /etc/services
Again, the command fails. Checking the log, we find a relevant AVC message:
avc: denied { search } for pid=8753 exe=/usr/bin/nmap name=nmap dev=dm-4 ino=100533 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:traceroute_t tclass=dir
We’ve made progress, but we haven’t
yet resolved the problem. Now, we’ve run afoul of
the traceroute_t
domain, lacking permission to
search the /usr/share/nmap
directory. Often
it’s convenient to avoid this sort of step-by-step
discovery of successive problems by running the system in permissive
mode. But since the system is attached to the Internet, we prefer to
continue running in enforcing mode. We could temporarily take the
system offline, but that could be inconvenient for some users. So we
choose to continue as we’ve begun.
Let’s authorize the traceroute_t
domain to search traceroute_t
directories. To do
so, add the following line to the
domains/program/traceroute.te
file:
allow traceroute_t traceroute_t:dir { search };
After adding the line, load the revised policy and retry Nmap, which again fails:
#make load
#nmap -sT 127.0.0.1
Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 17:46 UTC Unable to find nmap-services! Resorting to /etc/services
This time, the log shows that Nmap was again prohibited from reading
the
nmap-services
file but that the file is
correctly labeled with the new security context:
avc: denied { read } for pid=8822 exe=/usr/bin/nmap name=nmap-services dev=dm-4 ino=231156 scontext=root:sysadm_r:traceroute_t tcontext=system_u:object_r:traceroute_t tclass=file
Apparently, the traceroute_t
domain
isn’t authorized to read
traceroute_t
files. So we must add another line to
traceroute.te
, one authorizing the
traceroute_t
domain to read its own files:
allow traceroute_t traceroute_t:file { read };
Again, load the new policy and retry Nmap. This time, Nmap works as it should:
# nmap -sT 127.0.0.1
Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 18:02 UTC
Interesting ports on bill-a31 (127.0.0.1):
(The 1658 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
22/tcp open ssh
Nmap run completed -- 1 IP address (1 host up) scanned in 0.467 seconds
This case study is typical of what you may encounter when running programs with SELinux policies that are less than complete and error free.