Implementing SELinux as a Linux Security Module | ||
---|---|---|
<<< Previous | Next >>> |
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.
<<< Previous | Home | Next >>> |
System V IPC Hook Functions | IP Networking Hook Functions |