SELinux blocks CVE-2006-3626 (local privilege escalation)

Joshua Brindle has analyzed the recent /proc local privilege escalation vulnerability, CVE-2006-3626, and posted that SELinux targeted policy prevents exploitation.

It’d be an interesting and useful exercise to go back through historical vulnerabilities and determine how many of them would be mitigated by SELinux and similar technologies (Exec-shield, PIE etc.).

Mark Cox wrote an interesting paper, Risk Report: A year of Red Hat Enterprise Linux 4, which mentions that SELinux blocked the Lupper worm (also noting that that the policy version shipped by default would not have blocked a modified version of the worm).

Update:
SELinux mitigation confirmed by SANS. They also mention mounting /proc as nosuid as a workaround.

SELinux changes in the 2.6.17 kernel

Here’s a summary of the SELinux-related changes in the recently released 2.6.17 kernel.

Alexey Dobriyan

Darrel Goeddel

Steve Grubb

Serge Hallyn

Dustin Kirkland

Ingo Molnar

James Morris

Jamal Hadi Salim

Stephen Smalley

Ron Yorston

Catherine Zhang

  • TCP/UDP getpeersec. This provides a mechanism for applications to determine the security context of peers they’re communicating with, via IPSec xfrm labeling. For TCP, there’s a new SO_GETPEERSEC option for getsockopt() which returns the peer security context. For UDP, the peer security context may be retrieved on a per-message basis after setting a new IP_PASSEC socket option, then accessing the value via CMSG auxiliary data.
  • Authorize deletion of IPSec/xfrm labeling policies.

LWN Linux kernel quality survey

LWN has created a survey to elicit feedback on the quality of the 2.6 kernel series. This is a really important opportunity for the kernel development community to obtain data on how the development process is working, so please consider taking the survey. The results will be presented at the kernel summit by Jon Corbet.

Google Earth for Linux and SELinux

There’s a beta Google Earth client for Linux, which sounds like fun, except, like Picasa, it doesn’t work out of the box with SELinux.

Dan Walsh has provided the following simple workaround:

chcon -t unconfined_execmem_exec_t /usr/local/RealPlayer/realplay.bin
execstack -c /usr/local/google-earth/libcrypto.so.0.9.8

I don’t know why these apps need executable memory, and whether it’s truly safe to make these changes, as I don’t have the source to them.

Update:
Dan has more analysis here.

Update #2:
Dan received some email from google developers: looks like the problem snuck in at the last minute, and a fix is expected in the next release. Also, I installed it on my FC5 laptop running SELinux in enforcing mode and saw no problems, so it’s not affecting everyone.

SELinux workaround for Picasa

Many people will be trying out Google’s Picasa under Linux. Unfortunately, there’s no SELinux policy for the application yet, and Google have been advising people to disable SELinux on Fedora to run Picasa.

If affected, you do not need to disable SELinux.

A simple filesystem labeling workaround has been described in the following post:

http://groups.google.com/group/Google-Labs-Picasa-for-Linux/msg/06f6a1465a712dbc

# Set the executable module exception on *.so *.so.* and *.dll files

> find /opt/picasa -type f -iname '*.so' -o -iname '*.so.*' -o -iname '*.dll' -exec  chcon -t textrel_shlib_t {} \; 

It appears that some of the libraries they distribute require the execmod permission, which is not granted by default under SELinux. The above workaround above relabels the supplied libraries so that SELinux policy will consider them “safe” to perform operations constrained by the execmod permission. This in fact may be unsafe, although this workaround is certainly better than completely disabling SELinux.

You can read more about the details of execmod Ulrich Drepper’s document SELinux Memory Protection Tests.

Based on Ulrich’s commentary, it seems reasonable to assume that some element of the Picasa code being blocked by the SELinux policy needs to be reworked for security reasons. I’m not sure exactly which component(s) may be generating the policy violations, although it may of course be one of the third-party libraries. Ideally, we’ll be able work with the Google and/or third party developers to get the issue resolved correctly.

If you have any further information on this, contact the Fedora SELinux developers via the Fedora SELinux mailing list.

New secmark-based network controls for SELinux

Recently, I’ve been working on replacing the per-packet networking controls in SELinux. The kernel patches have been submitted upstream, and are available for use now as of 2.6.17-rc4-mm3.

The main reason for replacing the original controls is that they provided only a rudimentary form of static packet filtering, without utilizing any of the existing infrastructure offered by Netfilter/iptables. They also had a limited set of packet selectors. For an incoming packet, you could select on network interface, source address and source port; similar for an outgoing packet, but instead selecting on destination address and port. These selectors were hard-coded into the kernel labeling and enforcement mechanisms, as well as the security policy language. The latter was generally problematic as the types of security policies that people like to apply to traffic flow did not seem to map readily to the SELinux policy language constructs. While socket-based controls such as name_connect help somewhat, they do not provide a complete solution.

After investigating several approaches which turned out to have major drawbacks, including a major overhaul of the SELinux policy language constructs for networking, and pushing all labeling and access control out to iptables, a clean solution arose out of discussions at the recent SELinux developer summit.

The idea is to separate labeling and enforcement.

Specifically: use iptables to select and label packets, then use SELinux to enforce security policy using these packet labels. This utilizes the expressiveness of iptables rulesets, as well as the flexibility of any its many matches and targets, and powerful components such as connection tracking. At the same time, enforcement of security policy remains the responsibility of the SELinux AVC, and access control rules can be meaningfully analyzed as part of overall SELinux policy analysis. See figure 1 below for a simplified view of the new architecture.


     iptables                            SELinux AVC
    --------------------------------    ---------------------------------- 
   |                                |  |                                  |
   |  [ selection ]  [ labeling ]   |  |  [ access control enforcement ]  |
   |                                |  |                                  |
    --------------------------------    ---------------------------------- 
            |             |                            |
   >--------x-------------x---------------------> [ allowed? ] -------> accept
   packet flow                                         |
                                                       v
                                                      drop

                              Fig. 1

To facilitate this, a new field called secmark was added to the sk_buff structure used by the kernel to encapsulate network packets, aka the ‘skb’ or confusingly, skbuff. This is similar to the nfmark field used by the iptables MARK target for implementing a variety of network policy schemes, although secmark is specifically used by security subsystems for implementing security policy. It was added as a separate field to ensure that security policy and network policy (e.g. routing) can be managed independently. The network structures have been put on diets lately, so in adding this new field, DaveM has required me to volunteer to do some further reduction of the sk_buff structure in the future.

This secmark field is not specific to SELinux, or even iptables. It can potentially be used by other security subsystems and labeling mechanisms if required in the future.

For SELinux, we’ve now implemented a new object class, packet, and two permissions for controlling domain access to packets: send and recv. Another permission, relabelto, was added to the packet class, to control how domains can apply specific labels to packets.

Here’s an example of an access control rule with the new scheme:

allow httpd_t httpd_packet_t:packet { recv send };

Translated into English, it means: allow the domain httpd_t to send and receive packets labeled as httpd_packet_t. Where, typically, apache would run in the domain httpd_t. And that’s it entirely, for the SELinux access control rule.

The heavy lifting is done by iptables and the Netfilter framework, in deciding which packets to label as httpd_packet_t.

This is done with standard iptables matches for selecting packets, in conjunction with the new SECMARK and optionally CONNSECMARK targets. The SECMARK target simply labels packets with any valid security context.

iptables -t mangle -A INPUT -p tcp --dport 80 -j SECMARK --selctx system_u:object_r:httpd_packet_t:s0
iptables -t mangle -A OUTPUT -p tcp --sport 80 -j SECMARK --selctx system_u:object_r:httpd_packet_t:s0

In the above rather simplistic view, we are statically labeling packets arriving at and leaving from port 80 as httpd_packet_t, so that SELinux can then apply security policy to the packets based on these labels.

Note that we don’t have to just use the port selector here, we could also specify the interface, and also have different labels to identify different types of httpd packets (e.g. httpd_external_packet_t vs. httpd_internal_packet_t). These selection and labeling decisions can now be entirely specified with iptables syntax, not requiring any change to the SELinux policy language format. Any future selectors made available for iptables can be immediately put to use without changing any of the SELinux mechanism. So, we have labeling flexibility, which is much more in line with the general SELinux/Flask design goal of policy-flexibility.

This example is deliberately simplified, to demonstrate a the basic mechanism of selecting and labeling packets for SELinux. It has several drawbacks, some similar to the old controls, such as not filtering the ephemeral ports used on the connection (e.g. the source port chosen by the kernel of the client), nor handling ICMP messages specific to the connection.

With a relatively simple change to the iptables ruleset, using the new CONNSECMARK target, we can fully leverage the power of conntrack (or stateful inspection), so that only packets which are verified to be part of the connection or related to it are labeled as httpd_packet_t. This increases the security assurance of the new networking controls significantly, as well as making it extremely simple to specify SELinux policy for “complex” protocols such as FTP, which can open up multiple connections and operate in multiple modes (e.g. active vs. passive). As long as there are working conntrack protocol helpers available, SELinux can now leverage them, while knowing nothing about them.

The CONNSECMARK target is similar to the CONNMARK target, in that it deals with labels on connections, instead of just packets. With CONNSECMARK, you can either ‘save’ a packet mark to a connection or ‘restore’ a connection label to a packet. The first is used when a connection is setup, and the latter for all subsequent packets on the connection. The state match can be used to also specify the labeling of ‘related’ packets, such as ICMP packets or various protocol-specific packets such as those on a related FTP data connection.

Here’s an example of an iptables ruleset for vsftpd (derived from these testscripts):

# Ensure the FTP helper is loaded
modprobe ip_conntrack_ftp

# Create a chain for connection setup marking
iptables -t mangle -N SEL_FTPD

# Accept incoming connections, label SYN packets, and copy
# labels to connections.
iptables -t mangle -A INPUT -p tcp --dport 21 -m state --state NEW -j SEL_FTPD
iptables -t mangle -A SEL_FTPD -j SECMARK --selctx system_u:object_r:ftpd_packet_t:s0
iptables -t mangle -A SEL_FTPD -j CONNSECMARK --save
iptables -t mangle -A SEL_FTPD -j ACCEPT

# Common rules which copy connection labels to established
# and related packets.
iptables -t mangle -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
iptables -t mangle -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore

Now, while there are a few more rules here, two of which are common to all services, connection tracking is now being utilized, so, we get verification of the TCP handshake, TCP window tracking, labeling only for packets with valid ephemeral ports, and automatic labeling of related ICMP and FTP data connections.

The SELinux policy remains identical. We’re just using iptables/netfilter to determine what an ftpd packet is. SELinux just decides then whether a domain may send and/or receive the packet.

Here is the associated SELinux access control policy for vsftpd network traffic:

allow ftpd_t ftpd_packet_t:packet { recv send };

The full policy module for this, which includes a type definition for ftpd_packet_t and a few required odds and ends is taken from this directory of sample policies.

The SECMARK and CONNSECMARK targets cover both IPv4 and IPv6, so the above policy would also cover both protocols if the iptables rules are configured to label both protocols identically. The only catch for IPv6 at the moment is that the generic conntrack framework is not yet complete, and in fact, you cannot select it in the kernel concurrently with the old IP conntrack code. So, for the time being, you will either need to use the more limited NF conntrack code (which does include TCP and UDP support, but not an FTP helper); or use the IP conntrack code (recommended), which provides full coverage of IPv4, but requires static configuration for IPv6.

It should be very simple to programmatically generate iptables rules for services, and then include them with packages, along with their modular policy files. I can imagine a simple GUI tool, which, for each service, asks which port(s) and protocol(s) the service uses, and generates a standard ruleset. For common services, this information could be built into an internal database, along with known protocol helpers. Then, the admin could add further iptables selectors visually, such as network interface, IP address/mask etc. (And of course, have “revert to last state” and “revert to defaults” buttons).

To use this stuff, the easiest thing is to wait for your distro to roll it out, which will hopefully happen not long after the release of the 2.6.18 kernel, all things going well.

If you want to dive in now, grab the -mm3 kernel (or whichever latest kernel has the patches) and install it. Make sure you select the SECMARK and CONNSECMARK targets. The latter requires you to select ‘Connection tracking security mark support’.

In the SELinux config menu, I’d suggest leaving “NSA SELinux enable new secmark network controls by default” unchecked initially and overriding it manually with the selinux_compat_net boot parameter as required. Set it to ‘0’ to enable the new secmark controls, but not yet! (A related side note: try to avoid submitting a patch which by default, breaks Andrew Morton’s machine — it makes him Hulk angry!) You should now be able to boot into the new kernel with the old networking controls.

The next thing is to download the archive at:
http://people.redhat.com/jmorris/selinux/secmark/

This contains everything you need for userspace support, including patches for iptables, SELinux library patches, sample policies and Netfilter rulesets. You’ll need to apply the patches and rebuild your SELinux toolchain starting with libselinux and checkpolicy, then rebuild your policy and install it. Verify that it has 57 classes (see my previous entry on how to do that).

If this looks ok, you can try enabling the new network controls without any labeling rules or policy (echo 0 > /selinux/compat_net). For this, you need to go into permissive mode (or wait until you have good policy). By default, all traffic will now be marked as unlabeled_t, and you should see some AVC denials. From there, you can experiment with the example iptables rules and SELinux policies, until you have something which will work in enforcing mode.

To allow all unlabeled packets to all domains, the access rule looks like:

allow domain unlabeled_t:packet { send recv };

which is obviously not secure.

Of course, the above is just for people who want to do development and experimentation, not normal users: they will get the new controls and userspace updated properly via a yum or whatever their distro uses, once their distro folk have integrated all of the changes.

Please direct any questions or comments to the SELinux mailing list.

Developing SELinux in a modular policy environment

While the new modular policy stuff has been around for some time (and documented nicely from a pragmatic point of view by rising blog superstar, Dan Walsh), I’ve only recently had to delve into SELinux userland code again.

The modular policy stuff makes things much easier for admins and application developers, although as an SELinux developer who doesn’t spend a lot of time in the guts of userland, it’s been a nice new learning curve. With some help from Dan, I’m now able to easily do all of the things I used to do, and am seeing increasingly how much of a major advance the modular policy scheme is.

One thing in particular that I used to do, when adding new classes and perms, would be to rebuild the toolchain, then build a new policy, compile it to binary form, then use checkpolicy to verify some of its properties. With the monolithic scheme, you’d end up with a policy.conf file, the raw policy entries in text form, and compile it to a binary policy.20 (where 20 is the policy format version) file. This binary file could then just be written to /selinux/load to cause it to be loaded into the kernel.

With modular policy, the old-style monolithic policy.20 file is still regenerated during RPM installation, using the new modular base.pp file.

To do this manually and load the base policy (note: this kind of thing is for SELinux developers, not general users/admins or app devs), run:

 
# semodule -b /usr/share/selinux/targeted/base.pp

This will regenerate the monolithic equivalent:

/etc/selinux/targeted/policy/policy.20

You can also just create that file with the -n switch to semodule instead of -b.

Now, I can play with checkpolicy on this:

# checkpolicy -b -M /etc/selinux/targeted/policy/policy.20
checkpolicy:  loading policy configuration from /etc/selinux/targeted/policy/policy.20
libsepol.policydb_index_others: security:  3 users, 7 roles, 1216 types, 146 bools
libsepol.policydb_index_others: security: 1 sens, 256 cats
libsepol.policydb_index_others: security:  57 classes, 40353 rules, 17050 cond rules
checkpolicy:  policy configuration loaded

This parses the binary monolithic policy and simply reports some statistics. I’m particularly interested in this case to make sure that two new security classes are present (one of which I’ve been working on), verifying that the toolchain from libselinux onwards is functioning correctly, and that the kernel won’t get upset when the policy is loaded and the new classes are referenced.

For more fun, add the -d switch to the above, and you’ll be dropped into an interactive policy debugger.

More on the new work soon…

Open source scholarships in India

I was fascinated to read recently about the Google Code Jam in India, which attracted more than 14,000 entrants from the region. Very innovative and cool stuff — I think one of the big challenges into the future for open source and technology organizations in general is how to effectively engage with communities outside of the US, Canada and Western Europe.

I’d been wondering what my employer was up to in this area, and today, Red Hat announced an Open Source Scholarship program, in conjunction with IIT Bombay. This is actually the third annual such event, although I’m not sure on the details of previous years. This year, a number of scholarships are available for several amounts ranging from 50,000 Rs to 200,000 Rs, for students at colleges in India to develop Open Source projects. Registration is open now and closes May 31st.

SELinux changes in the 2.6.15 and 2.6.16 kernels

It’s been a while since I documented the SELinux kernel changes, the last being for 2.6.14. The 2.6.16 kernel has just been released, so here’s an update for this and the previous version.

2.6.16

ptrace security bug
This patch from Stephen Smalley fixes a security flaw in the handling of ptrace within SELinux (CVE-2006-1052). Still believed to be difficult to exploit usefully, especially as DAC is still operating.

Audit dependency
Finally make SELinux depend on CONFIG_AUDIT. SELinux had been increasingly depending on the CAPP audit framework, but now it is required to log permission denials. CONFIG_AUDIT_SYSCALL is still optional, but recommended, to ensure that as much information as possible is logged. Also, be sure to check /var/log/audit/audit.log for AVC messages.

Networking dependency
Also make SELinux depend on CONFIG_SECURITY_NETWORK, i.e. the LSM network hooks, as they are required for correct operation with local networking.

Private inode Memory leak fix
A memory leak was discovered and fixed. This was due to adding support for private inodes, which some filesystems use for internal housekeeping. Such inodes are not exposed to userland and do not require SELinux mediation and a patch was previously added to LSM to bypass security processing for them. However, some private inodes are not marked private until after allocation, so LSM has passed them to SELinux to have security blobs allocated, but then not to free them.

Clean up memory protection checks
This patch cleans up the memory protection handling code, to stop them from being re-applied to already executable mappings.

Labeled networking via IPsec
Trent Jaeger’s work on IPsec labeling finally went in (also see the paper). Very briefly, this allows mandatory access control to be extended across the network, so that you can control which security domains on different systems can talk to each other. Previously, such ideas were generally implemented for MLS systems by adding security labels to IP options. This new code is a major advance in the field, as it’s not MLS specific (not even SELinux specific), and makes use of IPsec in a number of ways. Firstly, rather than labeling packets individually, the IPsec security associations are labeled, and the security label for each packet is implied from that. Also, this labeled traffic is afforded all of the protections provided by IPsec (privacy, authentication), and makes use of ISAKMP negotiation (rather than implementing a new out of band security negotiation protocol, as I did with the defunct Selopt scheme). Catherine Zhang has also been doing a lot of work in this area, and 2.6.17 should feature her getpeersec API patches, which allow applications to determine the security contexts of peers.

Miscellaneous
A bunch of minor fixes went in, including removal of security struct magic numbers (a hangover from the days when SELinux was a loadable module via LSM), and general code cleanups, such as ARRAY_SIZE fixes, XFS symlink handling and removing unneeded casts on return from kmalloc & friends.

2.6.15

listxattr() fix
Daniel Drake fixed an interesting bug using Gentoo, where listxattr() failed if the specified buffer size was exactly correct. Typically, userland probes for a buffer size with NULL/0 values first, and this was the first time that someone actually used the value returned rather than starting off with some large default value which was always larger than needed. Textbook off-by-one bug.

Canonicalize getxattr()
This patch canonicalizes the value returned from getxattr() to be the value maintained internally by the kernel. This is to help with the transition to MLS/MCS without needing to relabel the entire filesystem. In such cases, the kernel can internally add an MLS field to the security label of a file if not present in the on-disk label, and the patch causes the kernel value to override the disk value, if different. This patch has a useful side-effect of enabling getxattr() for mountpoint labeled systems, which use in-kernel labeling.

Extend selinuxfs context node
The context node in selinuxfs (usually /selinux/context) was extended to allow userland (e.g. matchpathcon) to obtain canonicalized security contexts from the kernel (related to the above).

Disable automatic xattr setting on context-mounts
Stephen Smalley add a patch to prevent xattrs from being set automatically for files in filesystems using mountpoint labeling (a.k.a. context mounts), where the security label for files within the filesystem are set via the context= mount option. This was to maintain consistency with the fact that setxattr() is denied on such filesytems.

MLS file labeling compatibility
With MCS enabled by default in FC5, the MLS component of file labels becomes active. This patch provides backwards compatibility, so that files created under FC5 which now have MLS fields will be readable when MLS is not active on older systems (obviously, the older system will need an updated kernel with this patch).

Miscellaneous
As usual, a bunch of cleanups and various maintenance fixes, including removal of a bunch of unnecessary checks for (size_t < 0) in selinuxfs, and conversion to kzalloc(), saving over 1KB of kernel text.