aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 398d165f884e..179dd20bec0a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4588,6 +4588,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
4588static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) 4588static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4589{ 4589{
4590 struct sock *sk = sock->sk; 4590 struct sock *sk = sock->sk;
4591 struct sk_security_struct *sksec = sk->sk_security;
4591 u16 family; 4592 u16 family;
4592 int err; 4593 int err;
4593 4594
@@ -4599,11 +4600,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4599 family = sk->sk_family; 4600 family = sk->sk_family;
4600 if (family == PF_INET || family == PF_INET6) { 4601 if (family == PF_INET || family == PF_INET6) {
4601 char *addrp; 4602 char *addrp;
4602 struct sk_security_struct *sksec = sk->sk_security;
4603 struct common_audit_data ad; 4603 struct common_audit_data ad;
4604 struct lsm_network_audit net = {0,}; 4604 struct lsm_network_audit net = {0,};
4605 struct sockaddr_in *addr4 = NULL; 4605 struct sockaddr_in *addr4 = NULL;
4606 struct sockaddr_in6 *addr6 = NULL; 4606 struct sockaddr_in6 *addr6 = NULL;
4607 u16 family_sa = address->sa_family;
4607 unsigned short snum; 4608 unsigned short snum;
4608 u32 sid, node_perm; 4609 u32 sid, node_perm;
4609 4610
@@ -4613,11 +4614,20 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4613 * need to check address->sa_family as it is possible to have 4614 * need to check address->sa_family as it is possible to have
4614 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. 4615 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
4615 */ 4616 */
4616 switch (address->sa_family) { 4617 switch (family_sa) {
4618 case AF_UNSPEC:
4617 case AF_INET: 4619 case AF_INET:
4618 if (addrlen < sizeof(struct sockaddr_in)) 4620 if (addrlen < sizeof(struct sockaddr_in))
4619 return -EINVAL; 4621 return -EINVAL;
4620 addr4 = (struct sockaddr_in *)address; 4622 addr4 = (struct sockaddr_in *)address;
4623 if (family_sa == AF_UNSPEC) {
4624 /* see __inet_bind(), we only want to allow
4625 * AF_UNSPEC if the address is INADDR_ANY
4626 */
4627 if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
4628 goto err_af;
4629 family_sa = AF_INET;
4630 }
4621 snum = ntohs(addr4->sin_port); 4631 snum = ntohs(addr4->sin_port);
4622 addrp = (char *)&addr4->sin_addr.s_addr; 4632 addrp = (char *)&addr4->sin_addr.s_addr;
4623 break; 4633 break;
@@ -4629,15 +4639,14 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4629 addrp = (char *)&addr6->sin6_addr.s6_addr; 4639 addrp = (char *)&addr6->sin6_addr.s6_addr;
4630 break; 4640 break;
4631 default: 4641 default:
4632 /* Note that SCTP services expect -EINVAL, whereas 4642 goto err_af;
4633 * others expect -EAFNOSUPPORT.
4634 */
4635 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4636 return -EINVAL;
4637 else
4638 return -EAFNOSUPPORT;
4639 } 4643 }
4640 4644
4645 ad.type = LSM_AUDIT_DATA_NET;
4646 ad.u.net = &net;
4647 ad.u.net->sport = htons(snum);
4648 ad.u.net->family = family_sa;
4649
4641 if (snum) { 4650 if (snum) {
4642 int low, high; 4651 int low, high;
4643 4652
@@ -4649,10 +4658,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4649 snum, &sid); 4658 snum, &sid);
4650 if (err) 4659 if (err)
4651 goto out; 4660 goto out;
4652 ad.type = LSM_AUDIT_DATA_NET;
4653 ad.u.net = &net;
4654 ad.u.net->sport = htons(snum);
4655 ad.u.net->family = family;
4656 err = avc_has_perm(&selinux_state, 4661 err = avc_has_perm(&selinux_state,
4657 sksec->sid, sid, 4662 sksec->sid, sid,
4658 sksec->sclass, 4663 sksec->sclass,
@@ -4684,16 +4689,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4684 break; 4689 break;
4685 } 4690 }
4686 4691
4687 err = sel_netnode_sid(addrp, family, &sid); 4692 err = sel_netnode_sid(addrp, family_sa, &sid);
4688 if (err) 4693 if (err)
4689 goto out; 4694 goto out;
4690 4695
4691 ad.type = LSM_AUDIT_DATA_NET; 4696 if (family_sa == AF_INET)
4692 ad.u.net = &net;
4693 ad.u.net->sport = htons(snum);
4694 ad.u.net->family = family;
4695
4696 if (address->sa_family == AF_INET)
4697 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; 4697 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
4698 else 4698 else
4699 ad.u.net->v6info.saddr = addr6->sin6_addr; 4699 ad.u.net->v6info.saddr = addr6->sin6_addr;
@@ -4706,6 +4706,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
4706 } 4706 }
4707out: 4707out:
4708 return err; 4708 return err;
4709err_af:
4710 /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
4711 if (sksec->sclass == SECCLASS_SCTP_SOCKET)
4712 return -EINVAL;
4713 return -EAFNOSUPPORT;
4709} 4714}
4710 4715
4711/* This supports connect(2) and SCTP connect services such as sctp_connectx(3) 4716/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
@@ -4783,7 +4788,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
4783 ad.type = LSM_AUDIT_DATA_NET; 4788 ad.type = LSM_AUDIT_DATA_NET;
4784 ad.u.net = &net; 4789 ad.u.net = &net;
4785 ad.u.net->dport = htons(snum); 4790 ad.u.net->dport = htons(snum);
4786 ad.u.net->family = sk->sk_family; 4791 ad.u.net->family = address->sa_family;
4787 err = avc_has_perm(&selinux_state, 4792 err = avc_has_perm(&selinux_state,
4788 sksec->sid, sid, sksec->sclass, perm, &ad); 4793 sksec->sid, sid, sksec->sclass, perm, &ad);
4789 if (err) 4794 if (err)
@@ -5284,6 +5289,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5284 while (walk_size < addrlen) { 5289 while (walk_size < addrlen) {
5285 addr = addr_buf; 5290 addr = addr_buf;
5286 switch (addr->sa_family) { 5291 switch (addr->sa_family) {
5292 case AF_UNSPEC:
5287 case AF_INET: 5293 case AF_INET:
5288 len = sizeof(struct sockaddr_in); 5294 len = sizeof(struct sockaddr_in);
5289 break; 5295 break;
@@ -5291,7 +5297,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
5291 len = sizeof(struct sockaddr_in6); 5297 len = sizeof(struct sockaddr_in6);
5292 break; 5298 break;
5293 default: 5299 default:
5294 return -EAFNOSUPPORT; 5300 return -EINVAL;
5295 } 5301 }
5296 5302
5297 err = -EINVAL; 5303 err = -EINVAL;