9.9 Using Audit2allow

     

Most implementations of SELinux include Audit2allow, a tool that can help you create or customize a domain. Some fledgling SELinux administrators use Audit2allow indiscriminately, rendering their system less secure. One technical reviewer of this book terms Audit2allow "evil," not so much because of problems with the tool itself as because of the way it's often misused. In this section, I'll explain how to use Audit2allow more carefully , so that you can avoid this pitfall.

Audit2allow is a Perl script that processes recent AVC messages. It analyzes the messages it finds and prints allow rules that ”if added to the current policy ”would authorize the denied operations. Hence, you can go badly wrong by blindly accepting its recommendations. For instance, perhaps someone has attempted a prohibited operation. Adding the rules generated by Audit2allow will authorize the prohibited operation, but may also compromise system security. Another more subtle source of problems is that Audit2allow takes the current type architecture and file labels as given. Often it's appropriate ”or even necessary ”to create a new domain that encapsulates a program or operation, as I did in the preceding section. But Audit2allow provides no help in doing so.

Audit2allow is less than perfect in other ways. For instance, it is sometimes blind to prohibited operations. This can occur if the operation is covered by a dontaudit rule. It can also occur if AVC message caching has caused one or more messages to be suppressed.

A related weakness of Audit2allow is that it's not aware of the M4 macros used in implementing policies. So rules recommended by Audit2allow tend to be quite wordy and can result in cluttered policy files that are hard to understand.

However, despite its weaknesses, Audit2allow is a very useful tool when properly used.

The Audit2allow command has the following form:

 audit2allow [-d] [-v] [-l] [-i   inputfile   ] [-o   outputfile   ] 

The command takes the following options:


-d

Read input from the dmesg command, rather than a log file.


-v

Print verbose output.


-l

Ignore input preceding the most recent loading of the SELinux policy.


-i inputfile

Read input from inputfile.


-o outputfile

Append output to outputfile.

Typically use of Audit2allow takes the form:

 make reload # test program or operation here audit2allow -l -i /var/log/kernel 

By reloading the SELinux policy, you define a starting point before which Audit2allow, when run with the - l option, will ignore log entries. You then test the subject program or operation, generating AVC messages. Finally, Audit2allow analyzes these messages and prints recommended rules. You can capture these rules by redirecting Audit2allow's output to a file:

 audit2allow -l -i /var/log/kernel > /tmp/audit2allow 

You may be tempted to incorporate the rules generated by Audit2allow into your SELinux policy just to see what happens. Stifle this urge: it's likely that the generated rules include several that will weaken the security of your system.


It's often useful to set permissive mode before using Audit2allow. Doing so may avoid early termination of the test program. In general, it's best if the program runs to completion, since this generates more AVC messages than otherwise . However, setting permissive mode may compromise system security.

Let's consider the same case study in the preceding section, the Nmap program. But this time, let's use Audit2allow to help us create the nmap_t domain.

Let's begin, as before, with an FC file that refers to the nmap_t and nmap_exec_t domains:

 # nmap /usr/bin/nmap       --  system_u:object_r:nmap_exec_t /usr/share/nmap.*       system_u:object_r:nmap_t 

And let's create a basic TE file that defines these domains. This time, we'll also include a role declaration and a domain_auto_trans macro invocation. We'll need these because Audit2allow generates only AVC declarations. In particular, without the domain_auto_trans macro, Audit2allow will recommend authorizing the staff_t domain or another general-purpose domain to perform operations that we prefer to authorize only for the nmap_t domain. Here's our primitive TE file:

 ################################# # # Rules for the nmap_t domain. # # nmap_t is the domain for the nmap program. # nmap_exec_t is the type of the corresponding program. # type nmap_t, domain; type nmap_exec_t, file_type, sysadmfile, exec_type; role staff_r types nmap_t; domain_auto_trans(staff_t, nmap_exec_t, nmap_t) 

Let's now load the revised policy, set permissive mode, test Nmap, and examine the recommendations provided by Audit2allow:

 #  make load  #  setenforce 0  #  nmap -sT 127.0.0.1  Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 14:52 PDT 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.475 seconds #  setenforce 1  #  audit2allow -l -i /var/log/kernel  allow nmap_t amandaidx_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t amidxtape_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t biff_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t device_t:dir { search }; allow nmap_t dict_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t dns_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t etc_t:dir { search }; allow nmap_t etc_t:file { getattr read }; allow nmap_t fingerd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t ftp_data_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t ftp_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t http_cache_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t http_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t inetd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t innd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t ipp_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t ircd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t ld_so_cache_t:file { getattr read }; allow nmap_t ld_so_t:file { read }; allow nmap_t ldap_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t lib_t:dir { search }; allow nmap_t lib_t:lnk_file { read }; allow nmap_t locale_t:file { getattr read }; allow nmap_t monopd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t net_conf_t:file { getattr read }; allow nmap_t netif_lo_t:netif { rawip_send tcp_recv tcp_send }; allow nmap_t nmap_t:capability { net_raw }; allow nmap_t nmap_t:dir { search }; allow nmap_t nmap_t:file { getattr read }; allow nmap_t nmap_t:packet_socket { bind create getopt ioctl read setopt }; allow nmap_t nmap_t:rawip_socket { create setopt write }; allow nmap_t nmap_t:tcp_socket { connect create getopt setopt }; allow nmap_t nmap_t:udp_socket { create ioctl }; allow nmap_t nmap_t:unix_stream_socket { connect create }; allow nmap_t node_lo_t:node { rawip_send tcp_recv tcp_send }; allow nmap_t pop_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t port_t:tcp_socket { recv_msg send_msg }; allow nmap_t portmap_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t postgresql_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t printer_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t proc_t:dir { search }; allow nmap_t proc_t:file { getattr read }; allow nmap_t rlogin_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t rndc_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t root_t:dir { search }; allow nmap_t rsh_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t shlib_t:file { execute getattr read }; allow nmap_t smbd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t smtp_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t snmp_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t soundd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t spamd_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t ssh_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t sshd_t:fd { use }; allow nmap_t staff_devpts_t:chr_file { getattr read write }; allow nmap_t staff_home_dir_t:dir { search }; allow nmap_t telnet_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t transproxy_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t urandom_device_t:chr_file { getattr ioctl read }; allow nmap_t usr_t:dir { search }; allow nmap_t vnc_port_t:tcp_socket { recv_msg send_msg }; allow nmap_t xserver_port_t:tcp_socket { recv_msg send_msg }; 

Audit2allow produces many recommended rules. But notice that most of them have the same form:

 allow nmap_t   port   :tcp_socket { recv_msg send_msg }; 

where port refers to some TCP port. As it happens, these rules would work fine if added to the domain. But they're wordy and complicated because they don't take advantage of available M4 macros.

Using our knowledge of the macros available, which we can deepen by studying TE files distributed with SELinux, let's start over with a revised primitive TE file. Our revised TE file features a macro invocation, can_network , that authorizes network access:

 ################################# # # Rules for the nmap_t domain. # # nmap_t is the domain for the nmap program. # nmap_exec_t is the type of the corresponding program. # type nmap_t, domain; type nmap_exec_t, file_type, sysadmfile, exec_type; role staff_r types nmap_t; domain_auto_trans(staff_t, nmap_exec_t, nmap_t) can_network(nmap_t) 

After loading the new policy, testing Nmap, and running Audit2allow, we obtain the following set of recommended rules:

 allow nmap_t device_t:dir { search }; allow nmap_t etc_t:dir { search }; allow nmap_t etc_t:file { getattr read }; allow nmap_t ld_so_cache_t:file { getattr read }; allow nmap_t ld_so_t:file { read }; allow nmap_t lib_t:dir { search }; allow nmap_t lib_t:lnk_file { read }; allow nmap_t locale_t:file { getattr read }; allow nmap_t nmap_t:capability { net_raw }; allow nmap_t nmap_t:dir { search }; allow nmap_t nmap_t:file { getattr read }; allow nmap_t nmap_t:packet_socket { bind create getopt ioctl read setopt }; allow nmap_t nmap_t:rawip_socket { create setopt write }; allow nmap_t nmap_t:unix_stream_socket { connect create }; allow nmap_t proc_t:dir { search }; allow nmap_t proc_t:file { getattr read }; allow nmap_t root_t:dir { search }; allow nmap_t shlib_t:file { execute getattr read }; allow nmap_t sshd_t:fd { use }; allow nmap_t staff_devpts_t:chr_file { getattr read write }; allow nmap_t staff_home_dir_t:dir { search }; allow nmap_t urandom_device_t:chr_file { getattr ioctl read }; allow nmap_t usr_t:dir { search }; 

This set of recommended rules is substantially smaller than the original set, consisting of between one-third and one-half the number of lines.

Our next step is to review the recommendations to ensure that none is overly broad. We notice that all the rules pertain to the nmap_t domain. This is encouraging, since we were trying to ensure that we authorize only that domain for the special operations performed by Nmap. Ultimately, after careful study, we convince ourselves that the recommendations are appropriate and safe and add them to the nmap.te file, completing our task.

As you see, Audit2allow is no substitute for a solid understanding of the SELinux policy language, since intelligent use of Audit2allow requires such an understanding. But used judiciously, Audit2allow expedites and facilitates creation and customization of policies.

When customizing an existing policy, it's often helpful to avoid modifying the associated TE file. Otherwise, installing an updated policy may overwrite changes you've painstakingly devised. To avoid this problem, consider placing your changes in a file named domains/program/local.te . Be sure to create the corresponding FC file, file_contexts/program/local.fc ; otherwise, policy compilation may fail. Either file can be empty or contain only comments if no related specifications or declarations are needed.




SELinux. NSA's Open Source Security Enhanced Linux
Selinux: NSAs Open Source Security Enhanced Linux
ISBN: 0596007167
EAN: 2147483647
Year: 2003
Pages: 100
Authors: Bill McCarty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net