Category Archives: Linux

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.

selinuxnews.org rss feed

The RSS 2.0 feed for the news side of http://selinuxnews.org/ should be working ok now.

This is the feed url: http://selinuxnews.org/wp/index.php/feed/

Works for me via Bloglines, Firefox and Lifrea. If you can’t get it to work, let me know, especially if you know how to fix it.

User registration still needs to be configured (theoretically it works out of the box, but not the way I want it). Until then, as before, if anyone wants an account for posting news items, just email me and I’ll set it up manually.

SELinux Developer Summit

Today is the SELinux Developer Summit, with about thirty core SELinux developers. It’s been interesting to see how far things have come in just the last year in terms of both the technology advances and deployments of SELinux. It’s kind of disappointing to see the media characterize SELinux as just being a Red Hat thing, when it is a long standing open source community project.

In this developer summit, there are folk from (at least):

Atsec
Hitachi Software
Penn State University
Trusted Computer Solutions
MITRE
Debian
IBM
Ubuntu
HP
NSA
Tresys

Red Hat has three developers attending (i.e. less than 10%).

The symposium itself went really well, with high quality talks including contributions from BSD folk and even Microsoft Research. I believe the proceedings will be available soon.

selinuxnews.org

selinuxnews.org logo by Máirín Duffy

Say hello to Planet SELinux, a blog aggregator for the SELinux community; and SELinux News, for SELinux developers to post news about what they’re up to.

Layout and graphic design by the amazing mizmo, a.k.a. Máirín Duffy of the Fedora Project.

The news site is in beta mode, and SELinux developers will be able to create accounts and post articles there soon. In the meantime, if you want something posted, email me. The RSS feed for the news stories also needs to be fixed.

SELinux Symposium 2006 commences

SELinux Symposium

The SELinux Symposium in Baltimore has commenced, starting with two days of tutorials, then a technical conference, and a developer summit at the end of the week. The current tutorial on SELinux policy looks to be full.

Looks like there’ll be some interesting announcements regarding SELinux tools over the next few days. Stay tuned.

DNI award for Stephen Smalley

Stephen Smalley has been awarded with a Director of National Intelligence Fellows Award for his work on SELinux. Details here.

Director of National Intelligence, John D. Negroponte, presented the first DNI Fellows Awards to nine renowned members of the Intelligence Community at a ceremony today in the Eisenhower Executive Office Building. The DNI Fellows Awards program recognizes and rewards outstanding technical achievement within the Intelligence Community.

“These distinguished experts are the best of the best — professionals in whom we have enormous trust and confidence,” said John D. Negroponte, Director of National Intelligence. […] “

Anyone who’s had anything to do with the SELinux project will understand what a profound impact Stephen has had on the project, as well as both Linux and computer security in general. Congratulations, Stephen.

It’s amazing to consider that the leader of a Linux-based project is being recognized at such a high and critical level within the government.

The UK government also seems to be clued in. The second keynote speaker at the upcoming SELinux Symposium is Dr Steve Marsh, Director of the Central Sponsor for Information Assurance unit in the UK Cabinet Office.

Xen, FC5 & Security

Fedora Core 5 seems to be shaping up well, with the integration of Xen for virtualization. It’s pretty simple to get Xen up and running now with Fedora: just install FC5 Test 2 and follow the instructions at the Fedora Xen Quickstart page. You can manually install the hypervisor & Xen kernel, or let anaconda handle it by adding ‘xen0’ to the end of the kernel command line. Adding guests is trivial with Jeremy’s magic guest installer script.

Here’s a screenshot of a graphical guest install via VNC (click for full size):

Xen guest install via VNC

I only ran into a couple of problems:

  • The installer script is picky about the amount of memory available, and won’t proceed with less than 256MB allocated for the guest. This is not unreasonable, but I only have 512MB of memory on my laptop and the system wasn’t happy until I reduced Dom0’s memory to 192MB (using dom0_mem=192M as a hypervisor boot option).
  • I had to make sure that the primary network interface was eth0, as there’s quite a lot of work yet to do on the Xen networking scripts.

There’s a fedora-xen mailing list for users and developers.

From a security point of view, Xen is interesting in a number of ways. The simplest and perhaps most powerful is simply being able to run different services in different virtual machines, each locked down to the bare minimum for each task. On the same physical hardware, you can have say, a virtual machine for your web server and another for DNS. This provides strong logical security separation at a high level, while each of these VMs can be secured at the OS level with the fine-grained SELinux controls.

There seems to be a lot of research interest in security models for the hypervisor itself. The Xen tree includes a port of the sHype access control framework, which allows different models to be implemented in a similar manner to LSM. This is fun stuff, and certainly interesting for some very specific usage scenarios, but it’s not entirely clear to me yet how such a security framework can be made more generally useful.