Socket Hook Functions

The SELinux socket hook function implementations manage the security fields of socket objects and perform access control for socket operations. This section describes these hooks and their helper functions.

Managing Socket Security Fields

Socket Security Structure

Each user space socket structure (struct socket) has an associated inode structure, so the inode security structure is extensively used for socket objects as well. See the Section called Managing Inode Security Fields for a discussion of inode security structure and associated functions. A security field also exists in the network layer socket structure (struct sock), but this field can only be safely used for local/Unix domain sockets presently. A change to the TCP code would be required to ensure proper handling of this field for newly created server sockets created by a connection; such a change was included in the LSM kernel patch, but did not make it into the mainline kernel due to the rejection of the LSM networking hooks.

For local/Unix domain sockets, the sk_security_struct is used to store security information about the peer during connection establishment when the user socket is not yet allocated for the new connection. This structure is defined as follows:

struct sk_security_struct {
        struct sock *sk;
        security_id_t peer_sid;
}

Table 34. sk_security_struct

FieldDescription
skBack pointer to the associated sock structure.
peer_sidSID of the peer socket.

sk_alloc_security and sk_free_security

The sk_alloc_security and sk_free_security helper functions are the primitive allocation functions for sock security structures. They immediately return if the socket family is anything other than the local/Unix domain, as they cannot safely handle other kinds of sockets. Otherwise, they perform the usual allocation and initialization of the security structure.

selinux_socket_getpeersec

This hook function is called to handle the SO_PEERSEC getsockopt option. It first checks whether the socket is local/Unix domain, and if not, returns an error. Otherwise, it extracts the peer SID from the sock security structure, converts it to a context, and copies it to the user buffer.

selinux_socket_post_create

After a socket structure has been successfully created, this hook function is called to setup the inode security structure for the socket . It set the security class using socket_type_to_security_class, as shown in Table 35. The netlink socket class is further partitioned based the netlink protocol to support fine-grained control. If the socket does not match any of the specified types, it defaults to the generic socket security class. The hook function then sets the inode SID. The hook function is passed a flag indicating whether the socket is being created for kernel-internal use (e.g. for RPC) or for userspace. If the socket is for kernel-internal use, then it is labeled with the kernel initial SID. Otherwise, it is labeled with the SID of the creating task.

Table 35. Socket Security Classes

Protocol FamilyTypeProtocolSecurity Class
PF_UNIX

SOCK_STREAM
SOCK_SEQPACKET

ignoredunix_stream_socket
PF_UNIXSOCK_DGRAMignoredunix_dgram_socket
PF_INET/PF_INET6SOCK_STREAM

IPPROTO_IP
IPPROTO_TCP

tcp_socket
PF_INET/PF_INET6SOCK_DGRAM

IPPROTO_IP
IPPROTO_UDP

udp_socket
PF_INET/PF_INET6any other valueany other valuerawip_socket
PF_NETLINKignoredignorednetlink_*_socket
PF_PACKETignoredignoredpacket_socket
PF_KEYignoredignoredkey_socket

selinux_socket_accept

This hook function is called after a new socket has been created for the connection but prior to calling the protocol family's accept function. In addition to checking permission (discussed further in the Section called Controlling Socket Operations), this hook function sets the SID and security class in the inode security structure for the new socket. The new socket inherits the SID and security class of the listening socket. The new socket initialization must occur in this hook, since traffic can occur on the socket before the post_accept hook is called.

Controlling Socket Operations

socket_has_perm

This helper function checks whether a task has a particular permission to a socket. It first checks whether the socket is for kernel-internal use, and if so, returns success immediately. Otherwise, it sets up the auxiliary audit data and calls the AVC to check the permission.

General Socket Layer Hooks

The socket layer access control hook functions first check a permission between the current task and the socket using the socket_has_perm helper function. Some of the hook functions perform additional processing. The hook functions and the initial permission that they check are shown in Table 36. Any additional processing for the hook functions is then described after this table.

Table 36. Socket Layer Hook Permission Checks

Hook FunctionSourceTargetPermission
selinux_socket_createCurrentNewSocketcreate
selinux_socket_bindCurrentSocketbind
selinux_socket_connectCurrentSocketconnect
selinux_socket_listenCurrentSocketlisten
selinux_socket_acceptCurrentSocketaccept
selinux_socket_sendmsgCurrentSocketwrite
selinux_socket_recvmsgCurrentSocketread
selinux_socket_getsocknameCurrentSocketgetattr
selinux_socket_getpeernameCurrentSocketgetattr
selinux_socket_setsockoptCurrentSocketsetopt
selinux_socket_getsockoptCurrentSocketgetopt
selinux_socket_shutdownCurrentSocketshutdown

The selinux_socket_bind hook function performs an additional name_bind permission check between the socket and the SID associated with the port number for ports that are outside the range used to automatically bind. It also performs an additional node_bind permission check between the socket and the SID associated with the IP address.

The selinux_socket_connect hook function performs an additional name_connect permission check between the socket and the SID associated with the port number for TCP sockets. This check provides control over outbound TCP connections to particular ports distinct from the general controls over sending and receiving packets.

Controlling Receipt of Packets

The selinux_socket_sock_rcv_skb hook function is called by the sk_filter kernel function prior to applying any socket filters to control receipt of individual packets on a socket at a point where the destination socket and the receiving network device information is available. The hook function begins by checking whether the socket family corresponds with IPv4 or IPv6 and returning success immediately otherwise. It then checks for mapped IPv4 packets arriving via IPv6 sockets and adjusts the family information accordingly for later use in translation of the headers.

Unlike the previously discussed socket hook functions, this hook is passed a pointer to a network layer socket (sock) structure rather than a userspace socket structure. This hook function must (while holding the appropriate lock) first dereference the socket field of the sock structure and then dereference the inode field of the resulting socket structure in order to obtain security information about the receiving socket. However, security information is not always available, e.g. the socket may not be presently associated with an userspace socket (e.g. new server socket that has not yet been accepted, or a userspace socket that has been closed).

After obtaining the socket security information, the hook function must also obtain security information for the receiving network device. It calls the sel_netif_sids function to obtain the interface SID associated with the device. It then determines the right set of permissions to check based on the socket class, sets up auxiliary audit data, and calls selinux_parse_skb to parse the headers for address information to include in the audit data. It then performs permission checks between the socket SID and the SIDs associated with the receiving network interface, the remote host, and the source port, as shown in Table 37. Note that these permission checks differ from the original set of permission checks for packet receipt prior to the redesign for Linux 2.6.

Table 37. Permission Checks for Receiving a Packet on a Socket

SourceTargetPermission(s)
SocketNetworkInterface

udp_recv
tcp_recv
rawip_recv

SocketRemoteNode (Host)

udp_recv
tcp_recv
rawip_recv

SocketSourcePortrecv_msg

Hooks for Unix Domain Socket IPC

LSM places calls to two hooks, unix_stream_connect and unix_may_send, within the Unix domain socket code to provide consistent control over Unix domain socket IPC. These hooks are placed into the Unix domain socket code in order to have access to the destination socket, which is not available to the socket layer hooks. For sockets that use the file namespace, the inode hook functions could be used to control IPC, but this would not address sockets that use the abstract namespace. Hence, these two hooks were added by LSM.

The selinux_socket_unix_stream_connect hook function is called for Unix stream connections. It checks the connectto permission between the client socket and the listening socket. It also sets the peer SID fields in each of the peer sockets' security structures for later use by selinux_socket_getpeersec. The selinux_socket_unix_may_send hook function is called for Unix datagram communications. It checks the sendto permission between the sending socket and the receiving socket. These permission checks are summarized in Table 38.

Table 38. Unix Domain Permission Checks

HookSourceTargetPermission
unix_stream_connectClientSocketServerSocketconnectto
unix_may_sendSendingSocketReceivingSocketsendto