
From: James Morris <jmorris@redhat.com>

This patch adds a new SELinux access control, node_bind, which can be used
to restrict the local IP address to which an application may bind.



---

 25-akpm/security/selinux/avc.c                       |    5 ++
 25-akpm/security/selinux/hooks.c                     |   39 ++++++++++++++++---
 25-akpm/security/selinux/include/av_perm_to_string.h |    3 +
 25-akpm/security/selinux/include/av_permissions.h    |    3 +
 25-akpm/security/selinux/include/avc.h               |    1 
 5 files changed, 45 insertions(+), 6 deletions(-)

diff -puN security/selinux/avc.c~selinux-04-node_bind-control security/selinux/avc.c
--- 25/security/selinux/avc.c~selinux-04-node_bind-control	Fri Jan  9 12:49:33 2004
+++ 25-akpm/security/selinux/avc.c	Fri Jan  9 12:49:33 2004
@@ -636,6 +636,11 @@ void avc_audit(u32 ssid, u32 tsid,
 				       NIPQUAD(a->u.net.daddr));
 				if (a->u.net.port)
 					printk(" dest=%d", a->u.net.port);
+			} else if (a->u.net.saddr) {
+				printk(" saddr=%d.%d.%d.%d",
+				       NIPQUAD(a->u.net.saddr));
+				if (a->u.net.port)
+					printk(" src=%d", a->u.net.port);
 			} else if (a->u.net.port)
 				printk(" port=%d", a->u.net.port);
 			if (a->u.net.skb) {
diff -puN security/selinux/hooks.c~selinux-04-node_bind-control security/selinux/hooks.c
--- 25/security/selinux/hooks.c~selinux-04-node_bind-control	Fri Jan  9 12:49:33 2004
+++ 25-akpm/security/selinux/hooks.c	Fri Jan  9 12:49:33 2004
@@ -2403,7 +2403,7 @@ static int selinux_socket_bind(struct so
 
 	err = socket_has_perm(current, sock, SOCKET__BIND);
 	if (err)
-		return err;
+		goto out;
 
 	/*
 	 * If PF_INET, check name_bind permission for the port.
@@ -2415,7 +2415,7 @@ static int selinux_socket_bind(struct so
 		struct sockaddr_in *addr = (struct sockaddr_in *)address;
 		unsigned short snum = ntohs(addr->sin_port);
 		struct sock *sk = sock->sk;
-		u32 sid;
+		u32 sid, node_perm;
 
 		tsec = current->security;
 		isec = SOCK_INODE(sock)->i_security;
@@ -2425,18 +2425,45 @@ static int selinux_socket_bind(struct so
 			err = security_port_sid(sk->sk_family, sk->sk_type,
 						sk->sk_protocol, snum, &sid);
 			if (err)
-				return err;
+				goto out;
 			AVC_AUDIT_DATA_INIT(&ad,NET);
 			ad.u.net.port = snum;
 			err = avc_has_perm(isec->sid, sid,
 					   isec->sclass,
 					   SOCKET__NAME_BIND, NULL, &ad);
 			if (err)
-				return err;
+				goto out;
 		}
+		
+		switch(sk->sk_protocol) {
+		case IPPROTO_TCP:
+			node_perm = TCP_SOCKET__NODE_BIND;
+			break;
+			
+		case IPPROTO_UDP:
+			node_perm = UDP_SOCKET__NODE_BIND;
+			break;
+			
+		default:
+			node_perm = RAWIP_SOCKET__NODE_BIND;
+			break;
+		}
+		
+		err = security_node_sid(PF_INET, &addr->sin_addr.s_addr,
+		                        sizeof(addr->sin_addr.s_addr), &sid);
+		if (err)
+			goto out;
+		
+		AVC_AUDIT_DATA_INIT(&ad,NET);
+		ad.u.net.port = snum;
+		ad.u.net.saddr = addr->sin_addr.s_addr;
+		err = avc_has_perm(isec->sid, sid,
+		                   isec->sclass, node_perm, NULL, &ad);
+		if (err)
+			goto out;
 	}
-
-	return 0;
+out:
+	return err;
 }
 
 static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
diff -puN security/selinux/include/avc.h~selinux-04-node_bind-control security/selinux/include/avc.h
--- 25/security/selinux/include/avc.h~selinux-04-node_bind-control	Fri Jan  9 12:49:33 2004
+++ 25-akpm/security/selinux/include/avc.h	Fri Jan  9 12:49:33 2004
@@ -67,6 +67,7 @@ struct avc_audit_data {
 			struct sock *sk;
 			u16 port;
 			u32 daddr;
+			u32 saddr;
 		} net;
 		int cap;
 		int ipc_id;
diff -puN security/selinux/include/av_permissions.h~selinux-04-node_bind-control security/selinux/include/av_permissions.h
--- 25/security/selinux/include/av_permissions.h~selinux-04-node_bind-control	Fri Jan  9 12:49:33 2004
+++ 25-akpm/security/selinux/include/av_permissions.h	Fri Jan  9 12:49:33 2004
@@ -249,6 +249,7 @@
 #define TCP_SOCKET__CONNECTTO                     0x00400000UL
 #define TCP_SOCKET__NEWCONN                       0x00800000UL
 #define TCP_SOCKET__ACCEPTFROM                    0x01000000UL
+#define TCP_SOCKET__NODE_BIND                     0x02000000UL
 
 #define UDP_SOCKET__RELABELTO                     0x00000100UL
 #define UDP_SOCKET__RECV_MSG                      0x00080000UL
@@ -272,6 +273,7 @@
 #define UDP_SOCKET__SEND_MSG                      0x00100000UL
 #define UDP_SOCKET__RECVFROM                      0x00020000UL
 #define UDP_SOCKET__GETATTR                       0x00000010UL
+#define UDP_SOCKET__NODE_BIND                     0x00400000UL
 
 #define RAWIP_SOCKET__RELABELTO                   0x00000100UL
 #define RAWIP_SOCKET__RECV_MSG                    0x00080000UL
@@ -295,6 +297,7 @@
 #define RAWIP_SOCKET__SEND_MSG                    0x00100000UL
 #define RAWIP_SOCKET__RECVFROM                    0x00020000UL
 #define RAWIP_SOCKET__GETATTR                     0x00000010UL
+#define RAWIP_SOCKET__NODE_BIND                   0x00400000UL
 
 #define NODE__TCP_RECV                            0x00000001UL
 #define NODE__TCP_SEND                            0x00000002UL
diff -puN security/selinux/include/av_perm_to_string.h~selinux-04-node_bind-control security/selinux/include/av_perm_to_string.h
--- 25/security/selinux/include/av_perm_to_string.h~selinux-04-node_bind-control	Fri Jan  9 12:49:33 2004
+++ 25-akpm/security/selinux/include/av_perm_to_string.h	Fri Jan  9 12:49:33 2004
@@ -46,6 +46,9 @@ static struct av_perm_to_string av_perm_
    { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto" },
    { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn" },
    { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom" },
+   { SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind" },
+   { SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind" },
+   { SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind" },
    { SECCLASS_PROCESS, PROCESS__FORK, "fork" },
    { SECCLASS_PROCESS, PROCESS__TRANSITION, "transition" },
    { SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld" },

_
