Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ee92d46 authored by James Morris's avatar James Morris Committed by David S. Miller
Browse files

[SELinux]: Add support for DCCP

This patch implements SELinux kernel support for DCCP
(http://linux-net.osdl.org/index.php/DCCP), which is similar in
operation to TCP in terms of connected state between peers.

The SELinux support for DCCP is thus modeled on existing handling of
TCP.

A new DCCP socket class is introduced, to allow protocol
differentation.  The permissions for this class inherit all of the
socket permissions, as well as the current TCP permissions (node_bind,
name_bind etc). IPv4 and IPv6 are supported, although labeled
networking is not, at this stage.

Patches for SELinux userspace are at:
http://people.redhat.com/jmorris/selinux/dccp/user/



I've performed some basic testing, and it seems to be working as
expected.  Adding policy support is similar to TCP, the only real
difference being that it's a different protocol.

Acked-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 90833aa4
Loading
Loading
Loading
Loading
+58 −8
Original line number Diff line number Diff line
@@ -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;
@@ -3189,6 +3220,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
			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;
	}
@@ -3447,6 +3485,12 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
		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;
@@ -3778,6 +3822,12 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *
		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;
+1 −0
Original line number Diff line number Diff line
@@ -30,3 +30,4 @@
   S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
   S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
   S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
   S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL)
+8 −0
Original line number Diff line number Diff line
@@ -35,12 +35,16 @@
   S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv")
   S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send")
   S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
   S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv")
   S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send")
   S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
   S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
   S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
   S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send")
   S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv")
   S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
   S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv")
   S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send")
   S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
   S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
   S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom")
@@ -252,3 +256,7 @@
   S_(SECCLASS_KEY, KEY__LINK, "link")
   S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
   S_(SECCLASS_KEY, KEY__CREATE, "create")
   S_(SECCLASS_CONTEXT, CONTEXT__TRANSLATE, "translate")
   S_(SECCLASS_CONTEXT, CONTEXT__CONTAINS, "contains")
   S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
   S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
+32 −0
Original line number Diff line number Diff line
@@ -312,6 +312,8 @@
#define NODE__RAWIP_RECV                          0x00000010UL
#define NODE__RAWIP_SEND                          0x00000020UL
#define NODE__ENFORCE_DEST                        0x00000040UL
#define NODE__DCCP_RECV                           0x00000080UL
#define NODE__DCCP_SEND                           0x00000100UL

#define NETIF__TCP_RECV                           0x00000001UL
#define NETIF__TCP_SEND                           0x00000002UL
@@ -319,6 +321,8 @@
#define NETIF__UDP_SEND                           0x00000008UL
#define NETIF__RAWIP_RECV                         0x00000010UL
#define NETIF__RAWIP_SEND                         0x00000020UL
#define NETIF__DCCP_RECV                          0x00000040UL
#define NETIF__DCCP_SEND                          0x00000080UL

#define NETLINK_SOCKET__IOCTL                     0x00000001UL
#define NETLINK_SOCKET__READ                      0x00000002UL
@@ -970,3 +974,31 @@
#define KEY__LINK                                 0x00000010UL
#define KEY__SETATTR                              0x00000020UL
#define KEY__CREATE                               0x00000040UL

#define CONTEXT__TRANSLATE                        0x00000001UL
#define CONTEXT__CONTAINS                         0x00000002UL

#define DCCP_SOCKET__IOCTL                        0x00000001UL
#define DCCP_SOCKET__READ                         0x00000002UL
#define DCCP_SOCKET__WRITE                        0x00000004UL
#define DCCP_SOCKET__CREATE                       0x00000008UL
#define DCCP_SOCKET__GETATTR                      0x00000010UL
#define DCCP_SOCKET__SETATTR                      0x00000020UL
#define DCCP_SOCKET__LOCK                         0x00000040UL
#define DCCP_SOCKET__RELABELFROM                  0x00000080UL
#define DCCP_SOCKET__RELABELTO                    0x00000100UL
#define DCCP_SOCKET__APPEND                       0x00000200UL
#define DCCP_SOCKET__BIND                         0x00000400UL
#define DCCP_SOCKET__CONNECT                      0x00000800UL
#define DCCP_SOCKET__LISTEN                       0x00001000UL
#define DCCP_SOCKET__ACCEPT                       0x00002000UL
#define DCCP_SOCKET__GETOPT                       0x00004000UL
#define DCCP_SOCKET__SETOPT                       0x00008000UL
#define DCCP_SOCKET__SHUTDOWN                     0x00010000UL
#define DCCP_SOCKET__RECVFROM                     0x00020000UL
#define DCCP_SOCKET__SENDTO                       0x00040000UL
#define DCCP_SOCKET__RECV_MSG                     0x00080000UL
#define DCCP_SOCKET__SEND_MSG                     0x00100000UL
#define DCCP_SOCKET__NAME_BIND                    0x00200000UL
#define DCCP_SOCKET__NODE_BIND                    0x00400000UL
#define DCCP_SOCKET__NAME_CONNECT                 0x00800000UL
+2 −0
Original line number Diff line number Diff line
@@ -61,3 +61,5 @@
    S_("appletalk_socket")
    S_("packet")
    S_("key")
    S_("context")
    S_("dccp_socket")
Loading