Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Richard Haines and committed by
Paul Moore
d452930f 2277c7cd

+580 -47
+157
Documentation/security/SELinux-sctp.rst
··· 1 + SCTP SELinux Support 2 + ===================== 3 + 4 + Security Hooks 5 + =============== 6 + 7 + ``Documentation/security/LSM-sctp.rst`` describes the following SCTP security 8 + hooks with the SELinux specifics expanded below:: 9 + 10 + security_sctp_assoc_request() 11 + security_sctp_bind_connect() 12 + security_sctp_sk_clone() 13 + security_inet_conn_established() 14 + 15 + 16 + security_sctp_assoc_request() 17 + ----------------------------- 18 + Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the 19 + security module. Returns 0 on success, error on failure. 20 + :: 21 + 22 + @ep - pointer to sctp endpoint structure. 23 + @skb - pointer to skbuff of association packet. 24 + 25 + The security module performs the following operations: 26 + IF this is the first association on ``@ep->base.sk``, then set the peer 27 + sid to that in ``@skb``. This will ensure there is only one peer sid 28 + assigned to ``@ep->base.sk`` that may support multiple associations. 29 + 30 + ELSE validate the ``@ep->base.sk peer_sid`` against the ``@skb peer sid`` 31 + to determine whether the association should be allowed or denied. 32 + 33 + Set the sctp ``@ep sid`` to socket's sid (from ``ep->base.sk``) with 34 + MLS portion taken from ``@skb peer sid``. This will be used by SCTP 35 + TCP style sockets and peeled off connections as they cause a new socket 36 + to be generated. 37 + 38 + If IP security options are configured (CIPSO/CALIPSO), then the ip 39 + options are set on the socket. 40 + 41 + 42 + security_sctp_bind_connect() 43 + ----------------------------- 44 + Checks permissions required for ipv4/ipv6 addresses based on the ``@optname`` 45 + as follows:: 46 + 47 + ------------------------------------------------------------------ 48 + | BIND Permission Checks | 49 + | @optname | @address contains | 50 + |----------------------------|-----------------------------------| 51 + | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses | 52 + | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address | 53 + | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address | 54 + ------------------------------------------------------------------ 55 + 56 + ------------------------------------------------------------------ 57 + | CONNECT Permission Checks | 58 + | @optname | @address contains | 59 + |----------------------------|-----------------------------------| 60 + | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses | 61 + | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses | 62 + | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address | 63 + | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address | 64 + ------------------------------------------------------------------ 65 + 66 + 67 + ``Documentation/security/LSM-sctp.rst`` gives a summary of the ``@optname`` 68 + entries and also describes ASCONF chunk processing when Dynamic Address 69 + Reconfiguration is enabled. 70 + 71 + 72 + security_sctp_sk_clone() 73 + ------------------------- 74 + Called whenever a new socket is created by **accept**\(2) (i.e. a TCP style 75 + socket) or when a socket is 'peeled off' e.g userspace calls 76 + **sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new 77 + sockets sid and peer sid to that contained in the ``@ep sid`` and 78 + ``@ep peer sid`` respectively. 79 + :: 80 + 81 + @ep - pointer to current sctp endpoint structure. 82 + @sk - pointer to current sock structure. 83 + @sk - pointer to new sock structure. 84 + 85 + 86 + security_inet_conn_established() 87 + --------------------------------- 88 + Called when a COOKIE ACK is received where it sets the connection's peer sid 89 + to that in ``@skb``:: 90 + 91 + @sk - pointer to sock structure. 92 + @skb - pointer to skbuff of the COOKIE ACK packet. 93 + 94 + 95 + Policy Statements 96 + ================== 97 + The following class and permissions to support SCTP are available within the 98 + kernel:: 99 + 100 + class sctp_socket inherits socket { node_bind } 101 + 102 + whenever the following policy capability is enabled:: 103 + 104 + policycap extended_socket_class; 105 + 106 + SELinux SCTP support adds the ``name_connect`` permission for connecting 107 + to a specific port type and the ``association`` permission that is explained 108 + in the section below. 109 + 110 + If userspace tools have been updated, SCTP will support the ``portcon`` 111 + statement as shown in the following example:: 112 + 113 + portcon sctp 1024-1036 system_u:object_r:sctp_ports_t:s0 114 + 115 + 116 + SCTP Peer Labeling 117 + =================== 118 + An SCTP socket will only have one peer label assigned to it. This will be 119 + assigned during the establishment of the first association. Once the peer 120 + label has been assigned, any new associations will have the ``association`` 121 + permission validated by checking the socket peer sid against the received 122 + packets peer sid to determine whether the association should be allowed or 123 + denied. 124 + 125 + NOTES: 126 + 1) If peer labeling is not enabled, then the peer context will always be 127 + ``SECINITSID_UNLABELED`` (``unlabeled_t`` in Reference Policy). 128 + 129 + 2) As SCTP can support more than one transport address per endpoint 130 + (multi-homing) on a single socket, it is possible to configure policy 131 + and NetLabel to provide different peer labels for each of these. As the 132 + socket peer label is determined by the first associations transport 133 + address, it is recommended that all peer labels are consistent. 134 + 135 + 3) **getpeercon**\(3) may be used by userspace to retrieve the sockets peer 136 + context. 137 + 138 + 4) While not SCTP specific, be aware when using NetLabel that if a label 139 + is assigned to a specific interface, and that interface 'goes down', 140 + then the NetLabel service will remove the entry. Therefore ensure that 141 + the network startup scripts call **netlabelctl**\(8) to set the required 142 + label (see **netlabel-config**\(8) helper script for details). 143 + 144 + 5) The NetLabel SCTP peer labeling rules apply as discussed in the following 145 + set of posts tagged "netlabel" at: http://www.paul-moore.com/blog/t. 146 + 147 + 6) CIPSO is only supported for IPv4 addressing: ``socket(AF_INET, ...)`` 148 + CALIPSO is only supported for IPv6 addressing: ``socket(AF_INET6, ...)`` 149 + 150 + Note the following when testing CIPSO/CALIPSO: 151 + a) CIPSO will send an ICMP packet if an SCTP packet cannot be 152 + delivered because of an invalid label. 153 + b) CALIPSO does not send an ICMP packet, just silently discards it. 154 + 155 + 7) IPSEC is not supported as RFC 3554 - sctp/ipsec support has not been 156 + implemented in userspace (**racoon**\(8) or **ipsec_pluto**\(8)), 157 + although the kernel supports SCTP/IPSEC.
+261 -19
security/selinux/hooks.c
··· 67 67 #include <linux/tcp.h> 68 68 #include <linux/udp.h> 69 69 #include <linux/dccp.h> 70 + #include <linux/sctp.h> 71 + #include <net/sctp/structs.h> 70 72 #include <linux/quota.h> 71 73 #include <linux/un.h> /* for Unix socket types */ 72 74 #include <net/af_unix.h> /* for Unix socket types */ ··· 4136 4134 break; 4137 4135 } 4138 4136 4137 + #if IS_ENABLED(CONFIG_IP_SCTP) 4138 + case IPPROTO_SCTP: { 4139 + struct sctphdr _sctph, *sh; 4140 + 4141 + if (ntohs(ih->frag_off) & IP_OFFSET) 4142 + break; 4143 + 4144 + offset += ihlen; 4145 + sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); 4146 + if (sh == NULL) 4147 + break; 4148 + 4149 + ad->u.net->sport = sh->source; 4150 + ad->u.net->dport = sh->dest; 4151 + break; 4152 + } 4153 + #endif 4139 4154 default: 4140 4155 break; 4141 4156 } ··· 4226 4207 break; 4227 4208 } 4228 4209 4210 + #if IS_ENABLED(CONFIG_IP_SCTP) 4211 + case IPPROTO_SCTP: { 4212 + struct sctphdr _sctph, *sh; 4213 + 4214 + sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); 4215 + if (sh == NULL) 4216 + break; 4217 + 4218 + ad->u.net->sport = sh->source; 4219 + ad->u.net->dport = sh->dest; 4220 + break; 4221 + } 4222 + #endif 4229 4223 /* includes fragments */ 4230 4224 default: 4231 4225 break; ··· 4428 4396 sksec = sock->sk->sk_security; 4429 4397 sksec->sclass = sclass; 4430 4398 sksec->sid = sid; 4399 + /* Allows detection of the first association on this socket */ 4400 + if (sksec->sclass == SECCLASS_SCTP_SOCKET) 4401 + sksec->sctp_assoc_state = SCTP_ASSOC_UNSET; 4402 + 4431 4403 err = selinux_netlbl_socket_post_create(sock->sk, family); 4432 4404 } 4433 4405 ··· 4452 4416 if (err) 4453 4417 goto out; 4454 4418 4455 - /* 4456 - * If PF_INET or PF_INET6, check name_bind permission for the port. 4457 - * Multiple address binding for SCTP is not supported yet: we just 4458 - * check the first address now. 4459 - */ 4419 + /* If PF_INET or PF_INET6, check name_bind permission for the port. */ 4460 4420 family = sk->sk_family; 4461 4421 if (family == PF_INET || family == PF_INET6) { 4462 4422 char *addrp; ··· 4464 4432 unsigned short snum; 4465 4433 u32 sid, node_perm; 4466 4434 4467 - if (family == PF_INET) { 4435 + /* 4436 + * sctp_bindx(3) calls via selinux_sctp_bind_connect() 4437 + * that validates multiple binding addresses. Because of this 4438 + * need to check address->sa_family as it is possible to have 4439 + * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. 4440 + */ 4441 + if (address->sa_family == AF_INET) { 4468 4442 if (addrlen < sizeof(struct sockaddr_in)) { 4469 4443 err = -EINVAL; 4470 4444 goto out; ··· 4524 4486 node_perm = DCCP_SOCKET__NODE_BIND; 4525 4487 break; 4526 4488 4489 + case SECCLASS_SCTP_SOCKET: 4490 + node_perm = SCTP_SOCKET__NODE_BIND; 4491 + break; 4492 + 4527 4493 default: 4528 4494 node_perm = RAWIP_SOCKET__NODE_BIND; 4529 4495 break; ··· 4542 4500 ad.u.net->sport = htons(snum); 4543 4501 ad.u.net->family = family; 4544 4502 4545 - if (family == PF_INET) 4503 + if (address->sa_family == AF_INET) 4546 4504 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; 4547 4505 else 4548 4506 ad.u.net->v6info.saddr = addr6->sin6_addr; ··· 4556 4514 return err; 4557 4515 } 4558 4516 4559 - static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 4517 + /* This supports connect(2) and SCTP connect services such as sctp_connectx(3) 4518 + * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt 4519 + */ 4520 + static int selinux_socket_connect_helper(struct socket *sock, 4521 + struct sockaddr *address, int addrlen) 4560 4522 { 4561 4523 struct sock *sk = sock->sk; 4562 4524 struct sk_security_struct *sksec = sk->sk_security; ··· 4571 4525 return err; 4572 4526 4573 4527 /* 4574 - * If a TCP or DCCP socket, check name_connect permission for the port. 4528 + * If a TCP, DCCP or SCTP socket, check name_connect permission 4529 + * for the port. 4575 4530 */ 4576 4531 if (sksec->sclass == SECCLASS_TCP_SOCKET || 4577 - sksec->sclass == SECCLASS_DCCP_SOCKET) { 4532 + sksec->sclass == SECCLASS_DCCP_SOCKET || 4533 + sksec->sclass == SECCLASS_SCTP_SOCKET) { 4578 4534 struct common_audit_data ad; 4579 4535 struct lsm_network_audit net = {0,}; 4580 4536 struct sockaddr_in *addr4 = NULL; ··· 4584 4536 unsigned short snum; 4585 4537 u32 sid, perm; 4586 4538 4587 - if (sk->sk_family == PF_INET) { 4539 + /* sctp_connectx(3) calls via selinux_sctp_bind_connect() 4540 + * that validates multiple connect addresses. Because of this 4541 + * need to check address->sa_family as it is possible to have 4542 + * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. 4543 + */ 4544 + if (address->sa_family == AF_INET) { 4588 4545 addr4 = (struct sockaddr_in *)address; 4589 4546 if (addrlen < sizeof(struct sockaddr_in)) 4590 4547 return -EINVAL; ··· 4603 4550 4604 4551 err = sel_netport_sid(sk->sk_protocol, snum, &sid); 4605 4552 if (err) 4606 - goto out; 4553 + return err; 4607 4554 4608 - perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? 4609 - TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; 4555 + switch (sksec->sclass) { 4556 + case SECCLASS_TCP_SOCKET: 4557 + perm = TCP_SOCKET__NAME_CONNECT; 4558 + break; 4559 + case SECCLASS_DCCP_SOCKET: 4560 + perm = DCCP_SOCKET__NAME_CONNECT; 4561 + break; 4562 + case SECCLASS_SCTP_SOCKET: 4563 + perm = SCTP_SOCKET__NAME_CONNECT; 4564 + break; 4565 + } 4610 4566 4611 4567 ad.type = LSM_AUDIT_DATA_NET; 4612 4568 ad.u.net = &net; ··· 4623 4561 ad.u.net->family = sk->sk_family; 4624 4562 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); 4625 4563 if (err) 4626 - goto out; 4564 + return err; 4627 4565 } 4628 4566 4629 - err = selinux_netlbl_socket_connect(sk, address); 4567 + return 0; 4568 + } 4630 4569 4631 - out: 4632 - return err; 4570 + /* Supports connect(2), see comments in selinux_socket_connect_helper() */ 4571 + static int selinux_socket_connect(struct socket *sock, 4572 + struct sockaddr *address, int addrlen) 4573 + { 4574 + int err; 4575 + struct sock *sk = sock->sk; 4576 + 4577 + err = selinux_socket_connect_helper(sock, address, addrlen); 4578 + if (err) 4579 + return err; 4580 + 4581 + return selinux_netlbl_socket_connect(sk, address); 4633 4582 } 4634 4583 4635 4584 static int selinux_socket_listen(struct socket *sock, int backlog) ··· 4903 4830 u32 peer_sid = SECSID_NULL; 4904 4831 4905 4832 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || 4906 - sksec->sclass == SECCLASS_TCP_SOCKET) 4833 + sksec->sclass == SECCLASS_TCP_SOCKET || 4834 + sksec->sclass == SECCLASS_SCTP_SOCKET) 4907 4835 peer_sid = sksec->peer_sid; 4908 4836 if (peer_sid == SECSID_NULL) 4909 4837 return -ENOPROTOOPT; ··· 5015 4941 sk->sk_family == PF_UNIX) 5016 4942 isec->sid = sksec->sid; 5017 4943 sksec->sclass = isec->sclass; 4944 + } 4945 + 4946 + /* Called whenever SCTP receives an INIT chunk. This happens when an incoming 4947 + * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association 4948 + * already present). 4949 + */ 4950 + static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, 4951 + struct sk_buff *skb) 4952 + { 4953 + struct sk_security_struct *sksec = ep->base.sk->sk_security; 4954 + struct common_audit_data ad; 4955 + struct lsm_network_audit net = {0,}; 4956 + u8 peerlbl_active; 4957 + u32 peer_sid = SECINITSID_UNLABELED; 4958 + u32 conn_sid; 4959 + int err = 0; 4960 + 4961 + if (!selinux_policycap_extsockclass) 4962 + return 0; 4963 + 4964 + peerlbl_active = selinux_peerlbl_enabled(); 4965 + 4966 + if (peerlbl_active) { 4967 + /* This will return peer_sid = SECSID_NULL if there are 4968 + * no peer labels, see security_net_peersid_resolve(). 4969 + */ 4970 + err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family, 4971 + &peer_sid); 4972 + if (err) 4973 + return err; 4974 + 4975 + if (peer_sid == SECSID_NULL) 4976 + peer_sid = SECINITSID_UNLABELED; 4977 + } 4978 + 4979 + if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) { 4980 + sksec->sctp_assoc_state = SCTP_ASSOC_SET; 4981 + 4982 + /* Here as first association on socket. As the peer SID 4983 + * was allowed by peer recv (and the netif/node checks), 4984 + * then it is approved by policy and used as the primary 4985 + * peer SID for getpeercon(3). 4986 + */ 4987 + sksec->peer_sid = peer_sid; 4988 + } else if (sksec->peer_sid != peer_sid) { 4989 + /* Other association peer SIDs are checked to enforce 4990 + * consistency among the peer SIDs. 4991 + */ 4992 + ad.type = LSM_AUDIT_DATA_NET; 4993 + ad.u.net = &net; 4994 + ad.u.net->sk = ep->base.sk; 4995 + err = avc_has_perm(sksec->peer_sid, peer_sid, sksec->sclass, 4996 + SCTP_SOCKET__ASSOCIATION, &ad); 4997 + if (err) 4998 + return err; 4999 + } 5000 + 5001 + /* Compute the MLS component for the connection and store 5002 + * the information in ep. This will be used by SCTP TCP type 5003 + * sockets and peeled off connections as they cause a new 5004 + * socket to be generated. selinux_sctp_sk_clone() will then 5005 + * plug this into the new socket. 5006 + */ 5007 + err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid); 5008 + if (err) 5009 + return err; 5010 + 5011 + ep->secid = conn_sid; 5012 + ep->peer_secid = peer_sid; 5013 + 5014 + /* Set any NetLabel labels including CIPSO/CALIPSO options. */ 5015 + return selinux_netlbl_sctp_assoc_request(ep, skb); 5016 + } 5017 + 5018 + /* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting 5019 + * based on their @optname. 5020 + */ 5021 + static int selinux_sctp_bind_connect(struct sock *sk, int optname, 5022 + struct sockaddr *address, 5023 + int addrlen) 5024 + { 5025 + int len, err = 0, walk_size = 0; 5026 + void *addr_buf; 5027 + struct sockaddr *addr; 5028 + struct socket *sock; 5029 + 5030 + if (!selinux_policycap_extsockclass) 5031 + return 0; 5032 + 5033 + /* Process one or more addresses that may be IPv4 or IPv6 */ 5034 + sock = sk->sk_socket; 5035 + addr_buf = address; 5036 + 5037 + while (walk_size < addrlen) { 5038 + addr = addr_buf; 5039 + switch (addr->sa_family) { 5040 + case AF_INET: 5041 + len = sizeof(struct sockaddr_in); 5042 + break; 5043 + case AF_INET6: 5044 + len = sizeof(struct sockaddr_in6); 5045 + break; 5046 + default: 5047 + return -EAFNOSUPPORT; 5048 + } 5049 + 5050 + err = -EINVAL; 5051 + switch (optname) { 5052 + /* Bind checks */ 5053 + case SCTP_PRIMARY_ADDR: 5054 + case SCTP_SET_PEER_PRIMARY_ADDR: 5055 + case SCTP_SOCKOPT_BINDX_ADD: 5056 + err = selinux_socket_bind(sock, addr, len); 5057 + break; 5058 + /* Connect checks */ 5059 + case SCTP_SOCKOPT_CONNECTX: 5060 + case SCTP_PARAM_SET_PRIMARY: 5061 + case SCTP_PARAM_ADD_IP: 5062 + case SCTP_SENDMSG_CONNECT: 5063 + err = selinux_socket_connect_helper(sock, addr, len); 5064 + if (err) 5065 + return err; 5066 + 5067 + /* As selinux_sctp_bind_connect() is called by the 5068 + * SCTP protocol layer, the socket is already locked, 5069 + * therefore selinux_netlbl_socket_connect_locked() is 5070 + * is called here. The situations handled are: 5071 + * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2), 5072 + * whenever a new IP address is added or when a new 5073 + * primary address is selected. 5074 + * Note that an SCTP connect(2) call happens before 5075 + * the SCTP protocol layer and is handled via 5076 + * selinux_socket_connect(). 5077 + */ 5078 + err = selinux_netlbl_socket_connect_locked(sk, addr); 5079 + break; 5080 + } 5081 + 5082 + if (err) 5083 + return err; 5084 + 5085 + addr_buf += len; 5086 + walk_size += len; 5087 + } 5088 + 5089 + return 0; 5090 + } 5091 + 5092 + /* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */ 5093 + static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, 5094 + struct sock *newsk) 5095 + { 5096 + struct sk_security_struct *sksec = sk->sk_security; 5097 + struct sk_security_struct *newsksec = newsk->sk_security; 5098 + 5099 + /* If policy does not support SECCLASS_SCTP_SOCKET then call 5100 + * the non-sctp clone version. 5101 + */ 5102 + if (!selinux_policycap_extsockclass) 5103 + return selinux_sk_clone_security(sk, newsk); 5104 + 5105 + newsksec->sid = ep->secid; 5106 + newsksec->peer_sid = ep->peer_secid; 5107 + newsksec->sclass = sksec->sclass; 5108 + selinux_netlbl_sctp_sk_clone(sk, newsk); 5018 5109 } 5019 5110 5020 5111 static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, ··· 6802 6563 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security), 6803 6564 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid), 6804 6565 LSM_HOOK_INIT(sock_graft, selinux_sock_graft), 6566 + LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request), 6567 + LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone), 6568 + LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect), 6805 6569 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), 6806 6570 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), 6807 6571 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
+1 -1
security/selinux/include/classmap.h
··· 176 176 { COMMON_CAP2_PERMS, NULL } }, 177 177 { "sctp_socket", 178 178 { COMMON_SOCK_PERMS, 179 - "node_bind", NULL } }, 179 + "node_bind", "name_connect", "association", NULL } }, 180 180 { "icmp_socket", 181 181 { COMMON_SOCK_PERMS, 182 182 "node_bind", NULL } },
+20 -1
security/selinux/include/netlabel.h
··· 32 32 #include <linux/skbuff.h> 33 33 #include <net/sock.h> 34 34 #include <net/request_sock.h> 35 + #include <net/sctp/structs.h> 35 36 36 37 #include "avc.h" 37 38 #include "objsec.h" ··· 53 52 int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, 54 53 u16 family, 55 54 u32 sid); 56 - 55 + int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, 56 + struct sk_buff *skb); 57 57 int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); 58 58 void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); 59 + void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk); 59 60 int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); 60 61 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 61 62 struct sk_buff *skb, ··· 67 64 int level, 68 65 int optname); 69 66 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr); 67 + int selinux_netlbl_socket_connect_locked(struct sock *sk, 68 + struct sockaddr *addr); 70 69 71 70 #else 72 71 static inline void selinux_netlbl_cache_invalidate(void) ··· 118 113 return 0; 119 114 } 120 115 116 + static inline int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, 117 + struct sk_buff *skb) 118 + { 119 + return 0; 120 + } 121 121 static inline int selinux_netlbl_inet_conn_request(struct request_sock *req, 122 122 u16 family) 123 123 { 124 124 return 0; 125 125 } 126 126 static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) 127 + { 128 + return; 129 + } 130 + static inline void selinux_netlbl_sctp_sk_clone(struct sock *sk, sock *newsk) 127 131 { 128 132 return; 129 133 } ··· 156 142 } 157 143 static inline int selinux_netlbl_socket_connect(struct sock *sk, 158 144 struct sockaddr *addr) 145 + { 146 + return 0; 147 + } 148 + static inline int selinux_netlbl_socket_connect_locked(struct sock *sk, 149 + struct sockaddr *addr) 159 150 { 160 151 return 0; 161 152 }
+4
security/selinux/include/objsec.h
··· 130 130 u32 sid; /* SID of this object */ 131 131 u32 peer_sid; /* SID of peer */ 132 132 u16 sclass; /* sock security class */ 133 + enum { /* SCTP association state */ 134 + SCTP_ASSOC_UNSET = 0, 135 + SCTP_ASSOC_SET, 136 + } sctp_assoc_state; 133 137 }; 134 138 135 139 struct tun_security_struct {
+137 -26
security/selinux/netlabel.c
··· 249 249 sk = skb_to_full_sk(skb); 250 250 if (sk != NULL) { 251 251 struct sk_security_struct *sksec = sk->sk_security; 252 + 252 253 if (sksec->nlbl_state != NLBL_REQSKB) 253 254 return 0; 254 255 secattr = selinux_netlbl_sock_getattr(sk, sid); ··· 267 266 skbuff_setsid_return: 268 267 if (secattr == &secattr_storage) 269 268 netlbl_secattr_destroy(secattr); 269 + return rc; 270 + } 271 + 272 + /** 273 + * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association. 274 + * @ep: incoming association endpoint. 275 + * @skb: the packet. 276 + * 277 + * Description: 278 + * A new incoming connection is represented by @ep, ...... 279 + * Returns zero on success, negative values on failure. 280 + * 281 + */ 282 + int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, 283 + struct sk_buff *skb) 284 + { 285 + int rc; 286 + struct netlbl_lsm_secattr secattr; 287 + struct sk_security_struct *sksec = ep->base.sk->sk_security; 288 + struct sockaddr *addr; 289 + struct sockaddr_in addr4; 290 + #if IS_ENABLED(CONFIG_IPV6) 291 + struct sockaddr_in6 addr6; 292 + #endif 293 + 294 + if (ep->base.sk->sk_family != PF_INET && 295 + ep->base.sk->sk_family != PF_INET6) 296 + return 0; 297 + 298 + netlbl_secattr_init(&secattr); 299 + rc = security_netlbl_sid_to_secattr(ep->secid, &secattr); 300 + if (rc != 0) 301 + goto assoc_request_return; 302 + 303 + /* Move skb hdr address info to a struct sockaddr and then call 304 + * netlbl_conn_setattr(). 305 + */ 306 + if (ip_hdr(skb)->version == 4) { 307 + addr4.sin_family = AF_INET; 308 + addr4.sin_addr.s_addr = ip_hdr(skb)->saddr; 309 + addr = (struct sockaddr *)&addr4; 310 + #if IS_ENABLED(CONFIG_IPV6) 311 + } else { 312 + addr6.sin6_family = AF_INET6; 313 + addr6.sin6_addr = ipv6_hdr(skb)->saddr; 314 + addr = (struct sockaddr *)&addr6; 315 + #endif 316 + } 317 + 318 + rc = netlbl_conn_setattr(ep->base.sk, addr, &secattr); 319 + if (rc == 0) 320 + sksec->nlbl_state = NLBL_LABELED; 321 + 322 + assoc_request_return: 323 + netlbl_secattr_destroy(&secattr); 270 324 return rc; 271 325 } 272 326 ··· 372 316 sksec->nlbl_state = NLBL_LABELED; 373 317 else 374 318 sksec->nlbl_state = NLBL_UNSET; 319 + } 320 + 321 + /** 322 + * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock 323 + * @sk: current sock 324 + * @newsk: the new sock 325 + * 326 + * Description: 327 + * Called whenever a new socket is created by accept(2) or sctp_peeloff(3). 328 + */ 329 + void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) 330 + { 331 + struct sk_security_struct *sksec = sk->sk_security; 332 + struct sk_security_struct *newsksec = newsk->sk_security; 333 + 334 + newsksec->nlbl_state = sksec->nlbl_state; 375 335 } 376 336 377 337 /** ··· 541 469 } 542 470 543 471 /** 472 + * selinux_netlbl_socket_connect_helper - Help label a client-side socket on 473 + * connect 474 + * @sk: the socket to label 475 + * @addr: the destination address 476 + * 477 + * Description: 478 + * Attempt to label a connected socket with NetLabel using the given address. 479 + * Returns zero values on success, negative values on failure. 480 + * 481 + */ 482 + static int selinux_netlbl_socket_connect_helper(struct sock *sk, 483 + struct sockaddr *addr) 484 + { 485 + int rc; 486 + struct sk_security_struct *sksec = sk->sk_security; 487 + struct netlbl_lsm_secattr *secattr; 488 + 489 + /* connected sockets are allowed to disconnect when the address family 490 + * is set to AF_UNSPEC, if that is what is happening we want to reset 491 + * the socket */ 492 + if (addr->sa_family == AF_UNSPEC) { 493 + netlbl_sock_delattr(sk); 494 + sksec->nlbl_state = NLBL_REQSKB; 495 + rc = 0; 496 + return rc; 497 + } 498 + secattr = selinux_netlbl_sock_genattr(sk); 499 + if (secattr == NULL) { 500 + rc = -ENOMEM; 501 + return rc; 502 + } 503 + rc = netlbl_conn_setattr(sk, addr, secattr); 504 + if (rc == 0) 505 + sksec->nlbl_state = NLBL_CONNLABELED; 506 + 507 + return rc; 508 + } 509 + 510 + /** 511 + * selinux_netlbl_socket_connect_locked - Label a client-side socket on 512 + * connect 513 + * @sk: the socket to label 514 + * @addr: the destination address 515 + * 516 + * Description: 517 + * Attempt to label a connected socket that already has the socket locked 518 + * with NetLabel using the given address. 519 + * Returns zero values on success, negative values on failure. 520 + * 521 + */ 522 + int selinux_netlbl_socket_connect_locked(struct sock *sk, 523 + struct sockaddr *addr) 524 + { 525 + struct sk_security_struct *sksec = sk->sk_security; 526 + 527 + if (sksec->nlbl_state != NLBL_REQSKB && 528 + sksec->nlbl_state != NLBL_CONNLABELED) 529 + return 0; 530 + 531 + return selinux_netlbl_socket_connect_helper(sk, addr); 532 + } 533 + 534 + /** 544 535 * selinux_netlbl_socket_connect - Label a client-side socket on connect 545 536 * @sk: the socket to label 546 537 * @addr: the destination address ··· 616 481 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) 617 482 { 618 483 int rc; 619 - struct sk_security_struct *sksec = sk->sk_security; 620 - struct netlbl_lsm_secattr *secattr; 621 - 622 - if (sksec->nlbl_state != NLBL_REQSKB && 623 - sksec->nlbl_state != NLBL_CONNLABELED) 624 - return 0; 625 484 626 485 lock_sock(sk); 627 - 628 - /* connected sockets are allowed to disconnect when the address family 629 - * is set to AF_UNSPEC, if that is what is happening we want to reset 630 - * the socket */ 631 - if (addr->sa_family == AF_UNSPEC) { 632 - netlbl_sock_delattr(sk); 633 - sksec->nlbl_state = NLBL_REQSKB; 634 - rc = 0; 635 - goto socket_connect_return; 636 - } 637 - secattr = selinux_netlbl_sock_genattr(sk); 638 - if (secattr == NULL) { 639 - rc = -ENOMEM; 640 - goto socket_connect_return; 641 - } 642 - rc = netlbl_conn_setattr(sk, addr, secattr); 643 - if (rc == 0) 644 - sksec->nlbl_state = NLBL_CONNLABELED; 645 - 646 - socket_connect_return: 486 + rc = selinux_netlbl_socket_connect_locked(sk, addr); 647 487 release_sock(sk); 488 + 648 489 return rc; 649 490 }