Linux DevCenter    
 Published on Linux DevCenter (http://www.linuxdevcenter.com/)
 See this if you're having trouble printing code examples


O'Reilly Book Excerpts: SELinux

Adding Permissions Using SELinux

by Bill McCarty

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.

SELinux

Related Reading

SELinux
NSA's Open Source Security Enhanced Linux
By Bill McCarty

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.

Bill McCarty is associate professor of management information systems in the School of Business and Management of Azusa Pacific University, Azusa, California, and was previously associate professor of computer science, in which capacity he taught for ten years in Azusa Pacific's Master of Applied Computer Science program.


View catalog information for SELinux

Return to the Linux DevCenter.

Copyright © 2009 O'Reilly Media, Inc.