aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorRichard Haines <richard_c_haines@btinternet.com>2018-02-13 15:57:18 -0500
committerPaul Moore <paul@paul-moore.com>2018-02-26 17:45:25 -0500
commitd452930fd3b9031e59abfeddb2fa383f1403d61a (patch)
treebb3c24ac8fdf0065ec09f6c4b7e70488a2a5ab58 /security/selinux/hooks.c
parent2277c7cd75e39783eeb7512a6c35f8b4abbe1039 (diff)
selinux: Add SCTP support
The SELinux SCTP implementation is explained in: Documentation/security/SELinux-sctp.rst Signed-off-by: Richard Haines <richard_c_haines@btinternet.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c280
1 files changed, 261 insertions, 19 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8644d864e3c1..28a5c4ee0705 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -67,6 +67,8 @@
67#include <linux/tcp.h> 67#include <linux/tcp.h>
68#include <linux/udp.h> 68#include <linux/udp.h>
69#include <linux/dccp.h> 69#include <linux/dccp.h>
70#include <linux/sctp.h>
71#include <net/sctp/structs.h>
70#include <linux/quota.h> 72#include <linux/quota.h>
71#include <linux/un.h> /* for Unix socket types */ 73#include <linux/un.h> /* for Unix socket types */
72#include <net/af_unix.h> /* for Unix socket types */ 74#include <net/af_unix.h> /* for Unix socket types */
@@ -4134,6 +4136,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
4134 break; 4136 break;
4135 } 4137 }
4136 4138
4139#if IS_ENABLED(CONFIG_IP_SCTP)
4140 case IPPROTO_SCTP: {
4141 struct sctphdr _sctph, *sh;
4142
4143 if (ntohs(ih->frag_off) & IP_OFFSET)
4144 break;
4145
4146 offset += ihlen;
4147 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4148 if (sh == NULL)
4149 break;
4150
4151 ad->u.net->sport = sh->source;
4152 ad->u.net->dport = sh->dest;
4153 break;
4154 }
4155#endif
4137 default: 4156 default:
4138 break; 4157 break;
4139 } 4158 }
@@ -4207,6 +4226,19 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
4207 break; 4226 break;
4208 } 4227 }
4209 4228
4229#if IS_ENABLED(CONFIG_IP_SCTP)
4230 case IPPROTO_SCTP: {
4231 struct sctphdr _sctph, *sh;
4232
4233 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
4234 if (sh == NULL)
4235 break;
4236
4237 ad->u.net->sport = sh->source;
4238 ad->u.net->dport = sh->dest;
4239 break;
4240 }
4241#endif
4210 /* includes fragments */ 4242 /* includes fragments */
4211 default: 4243 default:
4212 break; 4244 break;
@@ -4396,6 +4428,10 @@ static int selinux_socket_post_create(struct socket *sock, int family,
4396 sksec = sock->sk->sk_security; 4428 sksec = sock->sk->sk_security;
4397 sksec->sclass = sclass; 4429 sksec->sclass = sclass;
4398 sksec->sid = sid; 4430 sksec->sid = sid;
4431 /* Allows detection of the first association on this socket */
4432 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4433 sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
4434
4399 err = selinux_netlbl_socket_post_create(sock->sk, family); 4435 err = selinux_netlbl_socket_post_create(sock->sk, family);
4400 } 4436 }
4401 4437
@@ -4416,11 +4452,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4416 if (err) 4452 if (err)
4417 goto out; 4453 goto out;
4418 4454
4419 /* 4455 /* If PF_INET or PF_INET6, check name_bind permission for the port. */
4420 * If PF_INET or PF_INET6, check name_bind permission for the port.
4421 * Multiple address binding for SCTP is not supported yet: we just
4422 * check the first address now.
4423 */
4424 family = sk->sk_family; 4456 family = sk->sk_family;
4425 if (family == PF_INET || family == PF_INET6) { 4457 if (family == PF_INET || family == PF_INET6) {
4426 char *addrp; 4458 char *addrp;
@@ -4432,7 +4464,13 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4432 unsigned short snum; 4464 unsigned short snum;
4433 u32 sid, node_perm; 4465 u32 sid, node_perm;
4434 4466
4435 if (family == PF_INET) { 4467 /*
4468 * sctp_bindx(3) calls via selinux_sctp_bind_connect()
4469 * that validates multiple binding addresses. Because of this
4470 * need to check address->sa_family as it is possible to have
4471 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4472 */
4473 if (address->sa_family == AF_INET) {
4436 if (addrlen < sizeof(struct sockaddr_in)) { 4474 if (addrlen < sizeof(struct sockaddr_in)) {
4437 err = -EINVAL; 4475 err = -EINVAL;
4438 goto out; 4476 goto out;
@@ -4486,6 +4524,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4486 node_perm = DCCP_SOCKET__NODE_BIND; 4524 node_perm = DCCP_SOCKET__NODE_BIND;
4487 break; 4525 break;
4488 4526
4527 case SECCLASS_SCTP_SOCKET:
4528 node_perm = SCTP_SOCKET__NODE_BIND;
4529 break;
4530
4489 default: 4531 default:
4490 node_perm = RAWIP_SOCKET__NODE_BIND; 4532 node_perm = RAWIP_SOCKET__NODE_BIND;
4491 break; 4533 break;
@@ -4500,7 +4542,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4500 ad.u.net->sport = htons(snum); 4542 ad.u.net->sport = htons(snum);
4501 ad.u.net->family = family; 4543 ad.u.net->family = family;
4502 4544
4503 if (family == PF_INET) 4545 if (address->sa_family == AF_INET)
4504 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; 4546 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
4505 else 4547 else
4506 ad.u.net->v6info.saddr = addr6->sin6_addr; 4548 ad.u.net->v6info.saddr = addr6->sin6_addr;
@@ -4514,7 +4556,11 @@ out:
4514 return err; 4556 return err;
4515} 4557}
4516 4558
4517static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 4559/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
4560 * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt
4561 */
4562static int selinux_socket_connect_helper(struct socket *sock,
4563 struct sockaddr *address, int addrlen)
4518{ 4564{
4519 struct sock *sk = sock->sk; 4565 struct sock *sk = sock->sk;
4520 struct sk_security_struct *sksec = sk->sk_security; 4566 struct sk_security_struct *sksec = sk->sk_security;
@@ -4525,10 +4571,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
4525 return err; 4571 return err;
4526 4572
4527 /* 4573 /*
4528 * If a TCP or DCCP socket, check name_connect permission for the port. 4574 * If a TCP, DCCP or SCTP socket, check name_connect permission
4575 * for the port.
4529 */ 4576 */
4530 if (sksec->sclass == SECCLASS_TCP_SOCKET || 4577 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4531 sksec->sclass == SECCLASS_DCCP_SOCKET) { 4578 sksec->sclass == SECCLASS_DCCP_SOCKET ||
4579 sksec->sclass == SECCLASS_SCTP_SOCKET) {
4532 struct common_audit_data ad; 4580 struct common_audit_data ad;
4533 struct lsm_network_audit net = {0,}; 4581 struct lsm_network_audit net = {0,};
4534 struct sockaddr_in *addr4 = NULL; 4582 struct sockaddr_in *addr4 = NULL;
@@ -4536,7 +4584,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
4536 unsigned short snum; 4584 unsigned short snum;
4537 u32 sid, perm; 4585 u32 sid, perm;
4538 4586
4539 if (sk->sk_family == PF_INET) { 4587 /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
4588 * that validates multiple connect addresses. Because of this
4589 * need to check address->sa_family as it is possible to have
4590 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4591 */
4592 if (address->sa_family == AF_INET) {
4540 addr4 = (struct sockaddr_in *)address; 4593 addr4 = (struct sockaddr_in *)address;
4541 if (addrlen < sizeof(struct sockaddr_in)) 4594 if (addrlen < sizeof(struct sockaddr_in))
4542 return -EINVAL; 4595 return -EINVAL;
@@ -4550,10 +4603,19 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
4550 4603
4551 err = sel_netport_sid(sk->sk_protocol, snum, &sid); 4604 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
4552 if (err) 4605 if (err)
4553 goto out; 4606 return err;
4554 4607
4555 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? 4608 switch (sksec->sclass) {
4556 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; 4609 case SECCLASS_TCP_SOCKET:
4610 perm = TCP_SOCKET__NAME_CONNECT;
4611 break;
4612 case SECCLASS_DCCP_SOCKET:
4613 perm = DCCP_SOCKET__NAME_CONNECT;
4614 break;
4615 case SECCLASS_SCTP_SOCKET:
4616 perm = SCTP_SOCKET__NAME_CONNECT;
4617 break;
4618 }
4557 4619
4558 ad.type = LSM_AUDIT_DATA_NET; 4620 ad.type = LSM_AUDIT_DATA_NET;
4559 ad.u.net = &net; 4621 ad.u.net = &net;
@@ -4561,13 +4623,24 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
4561 ad.u.net->family = sk->sk_family; 4623 ad.u.net->family = sk->sk_family;
4562 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); 4624 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
4563 if (err) 4625 if (err)
4564 goto out; 4626 return err;
4565 } 4627 }
4566 4628
4567 err = selinux_netlbl_socket_connect(sk, address); 4629 return 0;
4630}
4568 4631
4569out: 4632/* Supports connect(2), see comments in selinux_socket_connect_helper() */
4570 return err; 4633static int selinux_socket_connect(struct socket *sock,
4634 struct sockaddr *address, int addrlen)
4635{
4636 int err;
4637 struct sock *sk = sock->sk;
4638
4639 err = selinux_socket_connect_helper(sock, address, addrlen);
4640 if (err)
4641 return err;
4642
4643 return selinux_netlbl_socket_connect(sk, address);
4571} 4644}
4572 4645
4573static int selinux_socket_listen(struct socket *sock, int backlog) 4646static int selinux_socket_listen(struct socket *sock, int backlog)
@@ -4830,7 +4903,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
4830 u32 peer_sid = SECSID_NULL; 4903 u32 peer_sid = SECSID_NULL;
4831 4904
4832 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || 4905 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4833 sksec->sclass == SECCLASS_TCP_SOCKET) 4906 sksec->sclass == SECCLASS_TCP_SOCKET ||
4907 sksec->sclass == SECCLASS_SCTP_SOCKET)
4834 peer_sid = sksec->peer_sid; 4908 peer_sid = sksec->peer_sid;
4835 if (peer_sid == SECSID_NULL) 4909 if (peer_sid == SECSID_NULL)
4836 return -ENOPROTOOPT; 4910 return -ENOPROTOOPT;
@@ -4943,6 +5017,171 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
4943 sksec->sclass = isec->sclass; 5017 sksec->sclass = isec->sclass;
4944} 5018}
4945 5019
5020/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
5021 * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
5022 * already present).
5023 */
5024static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
5025 struct sk_buff *skb)
5026{
5027 struct sk_security_struct *sksec = ep->base.sk->sk_security;
5028 struct common_audit_data ad;
5029 struct lsm_network_audit net = {0,};
5030 u8 peerlbl_active;
5031 u32 peer_sid = SECINITSID_UNLABELED;
5032 u32 conn_sid;
5033 int err = 0;
5034
5035 if (!selinux_policycap_extsockclass)
5036 return 0;
5037
5038 peerlbl_active = selinux_peerlbl_enabled();
5039
5040 if (peerlbl_active) {
5041 /* This will return peer_sid = SECSID_NULL if there are
5042 * no peer labels, see security_net_peersid_resolve().
5043 */
5044 err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
5045 &peer_sid);
5046 if (err)
5047 return err;
5048
5049 if (peer_sid == SECSID_NULL)
5050 peer_sid = SECINITSID_UNLABELED;
5051 }
5052
5053 if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
5054 sksec->sctp_assoc_state = SCTP_ASSOC_SET;
5055
5056 /* Here as first association on socket. As the peer SID
5057 * was allowed by peer recv (and the netif/node checks),
5058 * then it is approved by policy and used as the primary
5059 * peer SID for getpeercon(3).
5060 */
5061 sksec->peer_sid = peer_sid;
5062 } else if (sksec->peer_sid != peer_sid) {
5063 /* Other association peer SIDs are checked to enforce
5064 * consistency among the peer SIDs.
5065 */
5066 ad.type = LSM_AUDIT_DATA_NET;
5067 ad.u.net = &net;
5068 ad.u.net->sk = ep->base.sk;
5069 err = avc_has_perm(sksec->peer_sid, peer_sid, sksec->sclass,
5070 SCTP_SOCKET__ASSOCIATION, &ad);
5071 if (err)
5072 return err;
5073 }
5074
5075 /* Compute the MLS component for the connection and store
5076 * the information in ep. This will be used by SCTP TCP type
5077 * sockets and peeled off connections as they cause a new
5078 * socket to be generated. selinux_sctp_sk_clone() will then
5079 * plug this into the new socket.
5080 */
5081 err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
5082 if (err)
5083 return err;
5084
5085 ep->secid = conn_sid;
5086 ep->peer_secid = peer_sid;
5087
5088 /* Set any NetLabel labels including CIPSO/CALIPSO options. */
5089 return selinux_netlbl_sctp_assoc_request(ep, skb);
5090}
5091
5092/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
5093 * based on their @optname.
5094 */
5095static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5096 struct sockaddr *address,
5097 int addrlen)
5098{
5099 int len, err = 0, walk_size = 0;
5100 void *addr_buf;
5101 struct sockaddr *addr;
5102 struct socket *sock;
5103
5104 if (!selinux_policycap_extsockclass)
5105 return 0;
5106
5107 /* Process one or more addresses that may be IPv4 or IPv6 */
5108 sock = sk->sk_socket;
5109 addr_buf = address;
5110
5111 while (walk_size < addrlen) {
5112 addr = addr_buf;
5113 switch (addr->sa_family) {
5114 case AF_INET:
5115 len = sizeof(struct sockaddr_in);
5116 break;
5117 case AF_INET6:
5118 len = sizeof(struct sockaddr_in6);
5119 break;
5120 default:
5121 return -EAFNOSUPPORT;
5122 }
5123
5124 err = -EINVAL;
5125 switch (optname) {
5126 /* Bind checks */
5127 case SCTP_PRIMARY_ADDR:
5128 case SCTP_SET_PEER_PRIMARY_ADDR:
5129 case SCTP_SOCKOPT_BINDX_ADD:
5130 err = selinux_socket_bind(sock, addr, len);
5131 break;
5132 /* Connect checks */
5133 case SCTP_SOCKOPT_CONNECTX:
5134 case SCTP_PARAM_SET_PRIMARY:
5135 case SCTP_PARAM_ADD_IP:
5136 case SCTP_SENDMSG_CONNECT:
5137 err = selinux_socket_connect_helper(sock, addr, len);
5138 if (err)
5139 return err;
5140
5141 /* As selinux_sctp_bind_connect() is called by the
5142 * SCTP protocol layer, the socket is already locked,
5143 * therefore selinux_netlbl_socket_connect_locked() is
5144 * is called here. The situations handled are:
5145 * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
5146 * whenever a new IP address is added or when a new
5147 * primary address is selected.
5148 * Note that an SCTP connect(2) call happens before
5149 * the SCTP protocol layer and is handled via
5150 * selinux_socket_connect().
5151 */
5152 err = selinux_netlbl_socket_connect_locked(sk, addr);
5153 break;
5154 }
5155
5156 if (err)
5157 return err;
5158
5159 addr_buf += len;
5160 walk_size += len;
5161 }
5162
5163 return 0;
5164}
5165
5166/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
5167static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
5168 struct sock *newsk)
5169{
5170 struct sk_security_struct *sksec = sk->sk_security;
5171 struct sk_security_struct *newsksec = newsk->sk_security;
5172
5173 /* If policy does not support SECCLASS_SCTP_SOCKET then call
5174 * the non-sctp clone version.
5175 */
5176 if (!selinux_policycap_extsockclass)
5177 return selinux_sk_clone_security(sk, newsk);
5178
5179 newsksec->sid = ep->secid;
5180 newsksec->peer_sid = ep->peer_secid;
5181 newsksec->sclass = sksec->sclass;
5182 selinux_netlbl_sctp_sk_clone(sk, newsk);
5183}
5184
4946static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, 5185static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4947 struct request_sock *req) 5186 struct request_sock *req)
4948{ 5187{
@@ -6563,6 +6802,9 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6563 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security), 6802 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6564 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid), 6803 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6565 LSM_HOOK_INIT(sock_graft, selinux_sock_graft), 6804 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6805 LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
6806 LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
6807 LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
6566 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), 6808 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6567 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), 6809 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6568 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), 6810 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),