diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 956137baf3e7..0cf98740ddc6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -58,6 +58,7 @@ #include <linux/netlink.h> #include <linux/tcp.h> #include <linux/udp.h> +#include <linux/dccp.h> #include <linux/quota.h> #include <linux/un.h> /* for Unix socket types */ #include <net/af_unix.h> /* for Unix socket types */ @@ -751,6 +752,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_UDP_SOCKET; else return SECCLASS_RAWIP_SOCKET; + case SOCK_DCCP: + return SECCLASS_DCCP_SOCKET; default: return SECCLASS_RAWIP_SOCKET; } @@ -2944,6 +2947,22 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, break; } + case IPPROTO_DCCP: { + struct dccp_hdr _dccph, *dh; + + if (ntohs(ih->frag_off) & IP_OFFSET) + break; + + offset += ihlen; + dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); + if (dh == NULL) + break; + + ad->u.net.sport = dh->dccph_sport; + ad->u.net.dport = dh->dccph_dport; + break; + } + default: break; } @@ -3004,6 +3023,18 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, break; } + case IPPROTO_DCCP: { + struct dccp_hdr _dccph, *dh; + + dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); + if (dh == NULL) + break; + + ad->u.net.sport = dh->dccph_sport; + ad->u.net.dport = dh->dccph_dport; + break; + } + /* includes fragments */ default: break; @@ -3188,7 +3219,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in case SECCLASS_UDP_SOCKET: node_perm = UDP_SOCKET__NODE_BIND; break; - + + case SECCLASS_DCCP_SOCKET: + node_perm = DCCP_SOCKET__NODE_BIND; + break; + default: node_perm = RAWIP_SOCKET__NODE_BIND; break; @@ -3226,16 +3261,17 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, return err; /* - * If a TCP socket, check name_connect permission for the port. + * If a TCP or DCCP socket, check name_connect permission for the port. */ isec = SOCK_INODE(sock)->i_security; - if (isec->sclass == SECCLASS_TCP_SOCKET) { + if (isec->sclass == SECCLASS_TCP_SOCKET || + isec->sclass == SECCLASS_DCCP_SOCKET) { struct sock *sk = sock->sk; struct avc_audit_data ad; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; unsigned short snum; - u32 sid; + u32 sid, perm; if (sk->sk_family == PF_INET) { addr4 = (struct sockaddr_in *)address; @@ -3254,11 +3290,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, if (err) goto out; + perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? + TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; + AVC_AUDIT_DATA_INIT(&ad,NET); ad.u.net.dport = htons(snum); ad.u.net.family = sk->sk_family; - err = avc_has_perm(isec->sid, sid, isec->sclass, - TCP_SOCKET__NAME_CONNECT, &ad); + err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); if (err) goto out; } @@ -3446,7 +3484,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, node_perm = NODE__TCP_RECV; recv_perm = TCP_SOCKET__RECV_MSG; break; - + + case SECCLASS_DCCP_SOCKET: + netif_perm = NETIF__DCCP_RECV; + node_perm = NODE__DCCP_RECV; + recv_perm = DCCP_SOCKET__RECV_MSG; + break; + default: netif_perm = NETIF__RAWIP_RECV; node_perm = NODE__RAWIP_RECV; @@ -3777,7 +3821,13 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * node_perm = NODE__TCP_SEND; send_perm = TCP_SOCKET__SEND_MSG; break; - + + case SECCLASS_DCCP_SOCKET: + netif_perm = NETIF__DCCP_SEND; + node_perm = NODE__DCCP_SEND; + send_perm = DCCP_SOCKET__SEND_MSG; + break; + default: netif_perm = NETIF__RAWIP_SEND; node_perm = NODE__RAWIP_SEND; |