Network Peer Controls07 Oct 2008 tags: ipsec netlabel selinux
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:
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.