Networking in NSA Security-Enhanced Linux

Break through the complexity of SELinux with a working example that shows how to add SELinux protection to a simple network server.
UNIX Domain Controls

Under Linux, UNIX domain sockets can be created in an abstract namespace independent of the filesystem. Additional hooks have been implemented to allow mediation of communication between UNIX domain sockets in the abstract namespace, as well as to provide control over the directionality of UNIX domain communications. The selinux_socket_unix_stream_connect hook checks the connectto permission when one UNIX domain socket attempts to establish a stream connection to another. The selinux_socket_unix_may_send hook checks the sendto permission when one UNIX domain socket transmits a datagram to another.

Another feature of UNIX domain sockets under Linux is the ability to authenticate a peer with the SO_PEERCRED socket option. This obtains the user ID, group ID and process ID of the peer. Under SELinux, we also can obtain the security context of a peer via a new socket option SO_PEERSEC. Calling getsockopt(2) with this option invokes the selinux_socket_getpeersec hook, which copies the security context to a buffer passed in by the user. This is used for local IPC, such as Security-Enhanced DBUS.

Netlink Controls

Netlink sockets provide message-based user/kernel communication. They are used, for example, to configure the kernel routing tables and IPSec machinery.

Netlink communication is asynchronous; messages can be sent in one context and received in another. When a Netlink packet is transmitted, the sender's security credentials in the form of a capability set are stored with the packet and checked on reception. This allows, for example, the kernel routing code to determine whether the user who sent a routing table update is really permitted to do so.

As part of the LSM Project, capabilities logic was moved out of the core kernel code and into a security module, so that LSMs could implement different security models if needed.

The SELinux module uses the selinux_netlink_send hook to copy only the NET_ADMIN capability to a Netlink packet being sent to the kernel.

The selinux_netlink_recv hook is invoked when security-critical messages are received. SELinux uses this hook to verify that the NET_ADMIN capability was copied to the packet during transmission and, thus, whether the sending process had the capability.

An increasing number of Netlink families are being implemented, and SELinux defines subclasses of Netlink sockets for those that are security-critical. This allows the socket controls to be configured on a per-Netlink family basis (for example, to differentiate routing messages from kernel audit messages).

SELinux also is able to determine, by using the selinux_netlink_send hook, whether messages on certain types of Netlink sockets are read or write operations and then apply the nlmsg_read or nlmsg_write permissions, respectively. This allows fine-grained policy to specify, for example, that a domain can read the routing table but not update it.

IPv4 and IPv6 Controls

SELinux adds several controls for TCP, UDP and Raw socket subclasses. The node_bind permission determines whether a socket can be bound to a specific type of node. This obviously is useful only for local IP addresses and can be used to restrict a dæmon to binding to a specific IP address.

The name_bind permission controls whether a socket can bind to a specific type of port. This permission is invoked only when the port number falls outside of the local port range. The local port range is where the kernel automatically allocates port numbers from (for example, when choosing the source port for an outgoing TCP connection) and can be configured through the sysctl net.ipv4.ip_local_port_range. On a typical system, this range is:

$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768    61000

Thus, name_bind is invoked only when a socket binds to a port outside this range. SELinux always invokes the permission for ports below 1024, regardless of the sysctl setting. Both of these bind-related controls are called from the selinux_socket_bind hook, which is invoked through the bind(2) system call.

The send_msg and recv_msg permissions are used to control whether a socket can send or receive messages through a specific type or port.

A set of permissions is implemented that controls whether packets can be received or sent over TCP, UDP or Raw sockets for specific types of netif and node objects. These are tcp_send, tcp_recv, udp_send, udp_recv, rawip_send and rawip_recv.

These message-based controls are invoked for incoming packets at the selinux_sock_rcv_skb hook, the first point in the networking stack where we reliably can associate a packet with a recipient socket. For outgoing packets, SELinux registers a Netfilter hook and catches them at the IP layer; outgoing packets still have socket ownership information attached at this stage.

All of the above controls are protocol-independent in that they operate on both IPv4 and IPv6 protocols.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Total bewilderment

derekfountain's picture

What a wonderful example of why kernel hackers shouldn't write magazine articles! I really wanted to understand this SELinux stuff, but this is an impenetrable mess.

Here's how not to do it: first, ensure you don't define your audience. I initially thought this was aimed at developers, but now I think perhaps it's aimed at systems administrators. Second, throw in a whole load of acronyms, right the beginning: MAC, TE, RBAC DAC, LSM (trying to ensure you never use them again in the rest of the piece). Then make life hard for the reader by giving a "general form" containing 3 lines, followed by an example containing 1 line. Still with us? Great. Throw in a few more undefined terms, like "security context", "target context" and "source context", then a few references to system calls (a couple of dozen should be enough). Next present a config file that is longer than the source of the program it is supposed to protect, plus tweaks to 3 other obscure files, the purpose of each remaining unexplained. Then throw in a "make" command without explaining that either. Finish up with a set of obscure commands to prove the example works, carefully labelling it as a "simple demonstration". Job done!

Perhaps I'm in a flippant mood this morning. Perhaps it's because I'm an application developer, not a sysadmin. Perhaps I haven't had enough caffeine. Or perhaps, just possibly, this article is written from the inside out, and is therefore only accessible to those who already understand what the heck it's on about.

If you want to understand mor

James M's picture

If you want to understand more about the underlying concepts, I'd suggest looking at the Faye Coker article listed in the resources,

The article is aimed at anyone interested in how SELinux works underneath, and documents a lot of previously undocumented aspects of the networking. I guess it may have been better to drop the introductory section (instead referring to other resources) and include a short glossary.

There is no Faye Cocker article

Anonymous's picture

I looked at that link,

There is no Faye Coker article listed on that page. I did a find on the entire web page for "faye" and "coker", nothing.