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.
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; } |
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.
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.
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 Family | Type | Protocol | Security Class | ||
---|---|---|---|---|---|
PF_UNIX |
| ignored | unix_stream_socket | ||
PF_UNIX | SOCK_DGRAM | ignored | unix_dgram_socket | ||
PF_INET/PF_INET6 | SOCK_STREAM |
| tcp_socket | ||
PF_INET/PF_INET6 | SOCK_DGRAM |
| udp_socket | ||
PF_INET/PF_INET6 | any other value | any other value | rawip_socket | ||
PF_NETLINK | ignored | ignored | netlink_*_socket | ||
PF_PACKET | ignored | ignored | packet_socket | ||
PF_KEY | ignored | ignored | key_socket |
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.
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.
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 Function | Source | Target | Permission |
---|---|---|---|
selinux_socket_create | Current | NewSocket | create |
selinux_socket_bind | Current | Socket | bind |
selinux_socket_connect | Current | Socket | connect |
selinux_socket_listen | Current | Socket | listen |
selinux_socket_accept | Current | Socket | accept |
selinux_socket_sendmsg | Current | Socket | write |
selinux_socket_recvmsg | Current | Socket | read |
selinux_socket_getsockname | Current | Socket | getattr |
selinux_socket_getpeername | Current | Socket | getattr |
selinux_socket_setsockopt | Current | Socket | setopt |
selinux_socket_getsockopt | Current | Socket | getopt |
selinux_socket_shutdown | Current | Socket | shutdown |
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.
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.
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.