From 0129565dcb026535035409875fae2ba1bb1a8b55 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 18 Jan 2004 18:37:54 -0800 Subject: [PATCH] [PATCH] selinux: Add node_bind control From: James Morris 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. --- security/selinux/avc.c | 5 +++ security/selinux/hooks.c | 39 +++++++++++++++++--- security/selinux/include/av_perm_to_string.h | 3 ++ security/selinux/include/av_permissions.h | 3 ++ security/selinux/include/avc.h | 1 + 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 0871fa4df9061..b6c792db23efb 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -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 --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 842b130950a4c..ec980b81264d4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2403,7 +2403,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in 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 socket *sock, struct sockaddr *address, in 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 socket *sock, struct sockaddr *address, in 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 --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 69ec417d9b0eb..0c616793b9b55 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -46,6 +46,9 @@ static struct av_perm_to_string av_perm_to_string[] = { { 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" }, diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 6cef301cbdbef..72e53d4bc7874 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -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 --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 3690fe1f3b380..9ecb739c80236 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -67,6 +67,7 @@ struct avc_audit_data { struct sock *sk; u16 port; u32 daddr; + u32 saddr; } net; int cap; int ipc_id; -- 2.53.0