aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-12-15 14:28:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-12-15 14:28:02 -0500
commitb5745c59627854afb3cd3f3860ee6f4571e2b633 (patch)
treedf9f3bb37b4cf0f3c52c970927bed4a843234e29 /security/selinux/hooks.c
parent29b1deb2a48a9dd02b93597aa4c055a24c0e989f (diff)
parentd93aca6050b10cd7d8b491637c3b5344c5680cac (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull SELinux fixes from James Morris. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: selinux: process labeled IPsec TCP SYN-ACK packets properly in selinux_ip_postroute() selinux: look for IPsec labels on both inbound and outbound packets selinux: handle TCP SYN-ACK packets correctly in selinux_ip_postroute() selinux: handle TCP SYN-ACK packets correctly in selinux_ip_output() selinux: fix possible memory leak
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c137
1 files changed, 112 insertions, 25 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 98b1caa1c1d3..419491d8e7d2 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -53,6 +53,7 @@
53#include <net/ip.h> /* for local_port_range[] */ 53#include <net/ip.h> /* for local_port_range[] */
54#include <net/sock.h> 54#include <net/sock.h>
55#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 55#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
56#include <net/inet_connection_sock.h>
56#include <net/net_namespace.h> 57#include <net/net_namespace.h>
57#include <net/netlabel.h> 58#include <net/netlabel.h>
58#include <linux/uaccess.h> 59#include <linux/uaccess.h>
@@ -3824,7 +3825,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3824 u32 nlbl_sid; 3825 u32 nlbl_sid;
3825 u32 nlbl_type; 3826 u32 nlbl_type;
3826 3827
3827 err = selinux_skb_xfrm_sid(skb, &xfrm_sid); 3828 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
3828 if (unlikely(err)) 3829 if (unlikely(err))
3829 return -EACCES; 3830 return -EACCES;
3830 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); 3831 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
@@ -3842,6 +3843,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3842 return 0; 3843 return 0;
3843} 3844}
3844 3845
3846/**
3847 * selinux_conn_sid - Determine the child socket label for a connection
3848 * @sk_sid: the parent socket's SID
3849 * @skb_sid: the packet's SID
3850 * @conn_sid: the resulting connection SID
3851 *
3852 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3853 * combined with the MLS information from @skb_sid in order to create
3854 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3855 * of @sk_sid. Returns zero on success, negative values on failure.
3856 *
3857 */
3858static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3859{
3860 int err = 0;
3861
3862 if (skb_sid != SECSID_NULL)
3863 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3864 else
3865 *conn_sid = sk_sid;
3866
3867 return err;
3868}
3869
3845/* socket security operations */ 3870/* socket security operations */
3846 3871
3847static int socket_sockcreate_sid(const struct task_security_struct *tsec, 3872static int socket_sockcreate_sid(const struct task_security_struct *tsec,
@@ -4448,7 +4473,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4448 struct sk_security_struct *sksec = sk->sk_security; 4473 struct sk_security_struct *sksec = sk->sk_security;
4449 int err; 4474 int err;
4450 u16 family = sk->sk_family; 4475 u16 family = sk->sk_family;
4451 u32 newsid; 4476 u32 connsid;
4452 u32 peersid; 4477 u32 peersid;
4453 4478
4454 /* handle mapped IPv4 packets arriving via IPv6 sockets */ 4479 /* handle mapped IPv4 packets arriving via IPv6 sockets */
@@ -4458,16 +4483,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4458 err = selinux_skb_peerlbl_sid(skb, family, &peersid); 4483 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
4459 if (err) 4484 if (err)
4460 return err; 4485 return err;
4461 if (peersid == SECSID_NULL) { 4486 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4462 req->secid = sksec->sid; 4487 if (err)
4463 req->peer_secid = SECSID_NULL; 4488 return err;
4464 } else { 4489 req->secid = connsid;
4465 err = security_sid_mls_copy(sksec->sid, peersid, &newsid); 4490 req->peer_secid = peersid;
4466 if (err)
4467 return err;
4468 req->secid = newsid;
4469 req->peer_secid = peersid;
4470 }
4471 4491
4472 return selinux_netlbl_inet_conn_request(req, family); 4492 return selinux_netlbl_inet_conn_request(req, family);
4473} 4493}
@@ -4727,6 +4747,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
4727static unsigned int selinux_ip_output(struct sk_buff *skb, 4747static unsigned int selinux_ip_output(struct sk_buff *skb,
4728 u16 family) 4748 u16 family)
4729{ 4749{
4750 struct sock *sk;
4730 u32 sid; 4751 u32 sid;
4731 4752
4732 if (!netlbl_enabled()) 4753 if (!netlbl_enabled())
@@ -4735,8 +4756,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
4735 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path 4756 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4736 * because we want to make sure we apply the necessary labeling 4757 * because we want to make sure we apply the necessary labeling
4737 * before IPsec is applied so we can leverage AH protection */ 4758 * before IPsec is applied so we can leverage AH protection */
4738 if (skb->sk) { 4759 sk = skb->sk;
4739 struct sk_security_struct *sksec = skb->sk->sk_security; 4760 if (sk) {
4761 struct sk_security_struct *sksec;
4762
4763 if (sk->sk_state == TCP_LISTEN)
4764 /* if the socket is the listening state then this
4765 * packet is a SYN-ACK packet which means it needs to
4766 * be labeled based on the connection/request_sock and
4767 * not the parent socket. unfortunately, we can't
4768 * lookup the request_sock yet as it isn't queued on
4769 * the parent socket until after the SYN-ACK is sent.
4770 * the "solution" is to simply pass the packet as-is
4771 * as any IP option based labeling should be copied
4772 * from the initial connection request (in the IP
4773 * layer). it is far from ideal, but until we get a
4774 * security label in the packet itself this is the
4775 * best we can do. */
4776 return NF_ACCEPT;
4777
4778 /* standard practice, label using the parent socket */
4779 sksec = sk->sk_security;
4740 sid = sksec->sid; 4780 sid = sksec->sid;
4741 } else 4781 } else
4742 sid = SECINITSID_KERNEL; 4782 sid = SECINITSID_KERNEL;
@@ -4806,27 +4846,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4806 * as fast and as clean as possible. */ 4846 * as fast and as clean as possible. */
4807 if (!selinux_policycap_netpeer) 4847 if (!selinux_policycap_netpeer)
4808 return selinux_ip_postroute_compat(skb, ifindex, family); 4848 return selinux_ip_postroute_compat(skb, ifindex, family);
4849
4850 secmark_active = selinux_secmark_enabled();
4851 peerlbl_active = selinux_peerlbl_enabled();
4852 if (!secmark_active && !peerlbl_active)
4853 return NF_ACCEPT;
4854
4855 sk = skb->sk;
4856
4809#ifdef CONFIG_XFRM 4857#ifdef CONFIG_XFRM
4810 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4858 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4811 * packet transformation so allow the packet to pass without any checks 4859 * packet transformation so allow the packet to pass without any checks
4812 * since we'll have another chance to perform access control checks 4860 * since we'll have another chance to perform access control checks
4813 * when the packet is on it's final way out. 4861 * when the packet is on it's final way out.
4814 * NOTE: there appear to be some IPv6 multicast cases where skb->dst 4862 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4815 * is NULL, in this case go ahead and apply access control. */ 4863 * is NULL, in this case go ahead and apply access control.
4816 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) 4864 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4865 * TCP listening state we cannot wait until the XFRM processing
4866 * is done as we will miss out on the SA label if we do;
4867 * unfortunately, this means more work, but it is only once per
4868 * connection. */
4869 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4870 !(sk != NULL && sk->sk_state == TCP_LISTEN))
4817 return NF_ACCEPT; 4871 return NF_ACCEPT;
4818#endif 4872#endif
4819 secmark_active = selinux_secmark_enabled();
4820 peerlbl_active = selinux_peerlbl_enabled();
4821 if (!secmark_active && !peerlbl_active)
4822 return NF_ACCEPT;
4823 4873
4824 /* if the packet is being forwarded then get the peer label from the
4825 * packet itself; otherwise check to see if it is from a local
4826 * application or the kernel, if from an application get the peer label
4827 * from the sending socket, otherwise use the kernel's sid */
4828 sk = skb->sk;
4829 if (sk == NULL) { 4874 if (sk == NULL) {
4875 /* Without an associated socket the packet is either coming
4876 * from the kernel or it is being forwarded; check the packet
4877 * to determine which and if the packet is being forwarded
4878 * query the packet directly to determine the security label. */
4830 if (skb->skb_iif) { 4879 if (skb->skb_iif) {
4831 secmark_perm = PACKET__FORWARD_OUT; 4880 secmark_perm = PACKET__FORWARD_OUT;
4832 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) 4881 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
@@ -4835,7 +4884,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4835 secmark_perm = PACKET__SEND; 4884 secmark_perm = PACKET__SEND;
4836 peer_sid = SECINITSID_KERNEL; 4885 peer_sid = SECINITSID_KERNEL;
4837 } 4886 }
4887 } else if (sk->sk_state == TCP_LISTEN) {
4888 /* Locally generated packet but the associated socket is in the
4889 * listening state which means this is a SYN-ACK packet. In
4890 * this particular case the correct security label is assigned
4891 * to the connection/request_sock but unfortunately we can't
4892 * query the request_sock as it isn't queued on the parent
4893 * socket until after the SYN-ACK packet is sent; the only
4894 * viable choice is to regenerate the label like we do in
4895 * selinux_inet_conn_request(). See also selinux_ip_output()
4896 * for similar problems. */
4897 u32 skb_sid;
4898 struct sk_security_struct *sksec = sk->sk_security;
4899 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4900 return NF_DROP;
4901 /* At this point, if the returned skb peerlbl is SECSID_NULL
4902 * and the packet has been through at least one XFRM
4903 * transformation then we must be dealing with the "final"
4904 * form of labeled IPsec packet; since we've already applied
4905 * all of our access controls on this packet we can safely
4906 * pass the packet. */
4907 if (skb_sid == SECSID_NULL) {
4908 switch (family) {
4909 case PF_INET:
4910 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4911 return NF_ACCEPT;
4912 break;
4913 case PF_INET6:
4914 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4915 return NF_ACCEPT;
4916 default:
4917 return NF_DROP_ERR(-ECONNREFUSED);
4918 }
4919 }
4920 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4921 return NF_DROP;
4922 secmark_perm = PACKET__SEND;
4838 } else { 4923 } else {
4924 /* Locally generated packet, fetch the security label from the
4925 * associated socket. */
4839 struct sk_security_struct *sksec = sk->sk_security; 4926 struct sk_security_struct *sksec = sk->sk_security;
4840 peer_sid = sksec->sid; 4927 peer_sid = sksec->sid;
4841 secmark_perm = PACKET__SEND; 4928 secmark_perm = PACKET__SEND;