In addition to Fallback Labels another new feature added to the 2.6.25 release of the Linux Kernel was the consolidation of the access control permissions for the different peer labeling mechanisms supported by SELinux. This consolidation has several benefits including better handling of traffic with multiple peer labels (all of the labels must be the same), elimination of confusing and duplicated per-packet access checks, and the creation of a new object class which abstracts away the underlying labeling protocol making policy development easier and more consistent.
Prior to the new network peer controls each peer labeling mechanism, NetLabel and Labeled IPsec, had separate access controls. In the early days of NetLabel this made sense as it allowed NetLabel development to proceed without impacting the existing Labeled IPsec mechanism, however, as time has progressed the additional access controls have proven problematic both from a code and policy management point of view. Those familiar with the old system know that in order to receive network traffic labeled with either NetLabel or Labeled IPsec you needed the following two allow rules (where socket_t is the receiving socket’s label and peer_t is the packet’s peer label):
The first allow rule allows NetLabel traffic whereas the second allow rule allows Labeled IPsec traffic. This duplication of access checks led to some interesting situations when only one peer labeling mechanism was in use, which happens to be the common case. The problem is that if you were using Labeled IPsec to browse the web you would need the following permissions:
You notice how the first access check requires access to unlabeled_t? This makes sense as NetLabel is not in use for this particular connection and is not able to generate a peer label, but it can be very confusing for users, policy writers and pretty much everyone else. The same problem happens when NetLabel is used and Labeled IPsec is not.
The solution to this was to consolidate the two access controls into a single access control. Doing so would not only simplify SELinux policy but also allow us to cleanup and consolidate much of the related SELinux kernel code. The new network peer controls work by deriving a single peer label for a network packet and then applying a single access check. In the rare case that multiple peer labels are present on a packet they must be equivalent for the packet to be considered valid; invalid packets are dropped. The resulting single access check looks like this:
allow socket_t peer_t:peer recv;
The new access check behaves exactly like the previous checks in that socket_t is the security label of the receiving socket and peer_t is the packet’s peer label (unlabeled_t when no peer labeling is in use). The difference being that it is only evaluated once per packet and is protocol agnostic; a big improvement on both counts.
While I believe most would agree that the new network peer controls are a welcome change, the fact remains that they are a change and a mechanism must exist to allow a smooth transition between the old and new controls. To solve this problem the concept of “policy capabilities” (yes, I know it is a poor name) was introduced which allows policy writers to selectively enable or disable kernel features. As of right now I am not aware of any SELinux policy, including the Reference Policy which enables the new controls. You can check your own system by running the following command (0 means the legacy controls are in use, 1 means the new controls are in use):
Later on I’ll explain how to enable the new network peer controls, but first I need to describe the new network ingress/egress access controls which are also enabled by the “network_peer_controls” policy capability. I don’t want anyone having a nasty surprise :) More on the ingress/egress controls in the next post.
One of the new features added to the 2.6.25 release of the Linux Kernel was the ability to specify fallback peer labels using NetLabel. This made it possible for system administrators to specify a peer label to be used in the absence of a peer labeling protocol such as CIPSO or Labeled IPsec. In this post I’ll try to provide a quick introduction on how to configure NetLabel to provide fallback peer labels.
The first step is to make sure you have all the right kernel and userspace bits in place. Any standard Linux distribution kernel 2.6.25 or greater that has NetLabel support should work. In addition to the kernel you will need to make sure the userspace utility, netlabelctl, supports the new configuration options; this requires netlabel_tools version 0.18 or greater. Once you have verified that you have the right versions installed and running, you can verify everything by running the following commands.
# netlabelctl -p mgmt version
NetLabel protocol version : 2
# netlabelctl -h
NetLabel Control Utility, version 0.18 (libnetlabel 0.18)
Usage: netlabelctl [<flags>] <module> [<commands>]
Flags:
-h : help/usage message
-p : make the output pretty
-t <secs> : timeout
-v : verbose mode
Modules and Commands:
mgmt : NetLabel management
version
protocols
map : Domain/Protocol mapping
add default|domain:<domain> protocol:<protocol>[,<extra>]
del default|domain:<domain>
list
unlbl : Unlabeled packet handling
accept on|off
add default|interface:<DEV> address:<ADDR>[/<MASK>]
label:<LABEL>
del default|interface:<DEV> address:<ADDR>[/<MASK>]
list
cipsov4 : CIPSO/IPv4 packet handling
add trans doi:<DOI> tags:<T1>,<Tn>
levels:<LL1>=<RL1>,<LLn>=<RLn>
categories:<LC1>=<RC1>,<LCn>=<RCn>
add pass doi:<DOI> tags:<T1>,<Tn>
del doi:<DOI>
list [doi:<DOI>]
The first command checks to see that the kernel speaks version 2 of the NetLabel control protocol which means that it understands the new fallback peer label configuration options. The second command verifies that you have netlabelctl version 0.18 installed and that it supports the fallback configuration commands that we will be using. If everything looks okay it is time to move on to the next step, building a test tool that we can use to verify the configuration. Obviously this isn’t a strict requirement for configuring the fallback label mechanism but it is a nice way to verify that your configuration is correct. The test tool I will be using here is a simple little test program I wrote some time ago to test basic peer label functionality for IPv4 TCP sockets, I call it getpeercon_server. Once you have downloaded the C source file you will need to compile it with the following command, if you are on a Fedora system make sure you have the libselinux-devel package installed.
As you can see the tool is very simple and takes a single argument, the TCP port to bind to a listen for connections. If you start the server on port 5000 and connect to it with telnet, netcat, or some other simple TCP application you should see something similar to what is shown below.
# ./getpeercon_server 5000
-> creating socket ... ok
-> listening on TCP port 5000 ... ok
-> waiting ... connect(127.0.0.1,NO_CONTEXT)
Hello NetLabel Fans!
-> connection closed
-> waiting ...
In the example above we can see that a client connected from localhost, 127.0.0.1, and there was no peer label information provided with the connection, NO_CONTEXT. Now lets configure a fallback peer label for localhost and try it again. Adding a fallback label is relatively simple and can be done with a single command. However, the example below executes two commands. The first command adds a fallback label, “system_u:object_r:netlabel_peer_t:s0”, to all traffic coming over the loopback interface, “lo”, from localhost, 127.0.0.1. The second command displays all of configured fallback labels; not a necessary step but helpful to ensure that you configured everything correctly.
# netlabelctl unlbl add interface:lo address:127.0.0.1 label:system_u:object_r:netlabel_peer_t:s0
# netlabelctl -p unlbl list
Accept unlabeled packets : on
Configured NetLabel address mappings (1)
interface: lo
address: 127.0.0.1/32
label: "system_u:object_r:netlabel_peer_t:s0"
Now, lets try our simple connection test again with our newly established fallback label configuration.
# ./getpeercon_server 5000
-> creating socket ... ok
-> listening on TCP port 5000 ... ok
-> waiting ... connect(127.0.0.1,system_u:object_r:netlabel_peer_t:s0)
Fallback Labels Are Really Cool!
-> connection closed
-> waiting ...
If you look at the output you will notice almost everything is the same except for one important thing, instead of NO_CONTEXT the test tool is displaying the fallback label we just configured. The kernel treats the NetLabel fallback label just the same as a normal peer label taken from a CIPSO tag or Labeled IPsec Security Association. This means that not only is the fallback label passed to applications that request it, it is also used when enforcing the LSM’s network security policy; in this case SELinux. However, it is important to remember that the fallback labels are overridden by peer labeling protocols. As a result, if both fallback peer label information and Labeled IPsec peer label information is available then the kernel will use the Labeled IPsec peer label information and ignore the fallback peer labels. Fallback peer labels can be configured based on the network interface, network address, and netmask or just network address and netmask when the default network interface is chosen.
Before you start making use of the NetLabel fallback labels, there are a few things you should take into consideration. First, while the fallback functionality was included in Linux Kernel 2.6.25 there was a small bug which prevented some IPv6 fallback labels from being displayed correctly using the “netlabelctl -p unlbl list” command; this has been fixed in kernel 2.6.26. Second, Fedora has not yet adopted version 0.18 of netlabel_tools which means that you will need to download and build netlabelctl separately to take advantage of the new fallback functionality. A Red Hat bugzilla entry has been filed to get the latest netlabel_tools package included in Fedora.
Thanks to James Morris for pointing out that the Linux Foundation Japan videos are now online. I’ve put a copy at the link below. All I ask is that you remember I had been in Japan less than a day when this was filmed and was still dealing with a 13 hour time difference :)