aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2013-12-10 14:58:01 -0500
committerPaul Moore <pmoore@redhat.com>2013-12-12 17:21:31 -0500
commitc0828e50485932b7e019df377a6b0a8d1ebd3080 (patch)
tree60d953c62261e7ec3b5b33e86e58a3d7286e1c4a /security
parent817eff718dca4e54d5721211ddde0914428fbb7c (diff)
selinux: process labeled IPsec TCP SYN-ACK packets properly in selinux_ip_postroute()
Due to difficulty in arriving at the proper security label for TCP SYN-ACK packets in selinux_ip_postroute(), we need to check packets while/before they are undergoing XFRM transforms instead of waiting until afterwards so that we can determine the correct security label. Reported-by: Janak Desai <Janak.Desai@gtri.gatech.edu> Cc: stable@vger.kernel.org Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8b2812312ae4..6db2e589a1f3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4850,22 +4850,31 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4850 * as fast and as clean as possible. */ 4850 * as fast and as clean as possible. */
4851 if (!selinux_policycap_netpeer) 4851 if (!selinux_policycap_netpeer)
4852 return selinux_ip_postroute_compat(skb, ifindex, family); 4852 return selinux_ip_postroute_compat(skb, ifindex, family);
4853
4854 secmark_active = selinux_secmark_enabled();
4855 peerlbl_active = selinux_peerlbl_enabled();
4856 if (!secmark_active && !peerlbl_active)
4857 return NF_ACCEPT;
4858
4859 sk = skb->sk;
4860
4853#ifdef CONFIG_XFRM 4861#ifdef CONFIG_XFRM
4854 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4862 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4855 * packet transformation so allow the packet to pass without any checks 4863 * packet transformation so allow the packet to pass without any checks
4856 * since we'll have another chance to perform access control checks 4864 * since we'll have another chance to perform access control checks
4857 * when the packet is on it's final way out. 4865 * when the packet is on it's final way out.
4858 * NOTE: there appear to be some IPv6 multicast cases where skb->dst 4866 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4859 * is NULL, in this case go ahead and apply access control. */ 4867 * is NULL, in this case go ahead and apply access control.
4860 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) 4868 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4869 * TCP listening state we cannot wait until the XFRM processing
4870 * is done as we will miss out on the SA label if we do;
4871 * unfortunately, this means more work, but it is only once per
4872 * connection. */
4873 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4874 !(sk != NULL && sk->sk_state == TCP_LISTEN))
4861 return NF_ACCEPT; 4875 return NF_ACCEPT;
4862#endif 4876#endif
4863 secmark_active = selinux_secmark_enabled();
4864 peerlbl_active = selinux_peerlbl_enabled();
4865 if (!secmark_active && !peerlbl_active)
4866 return NF_ACCEPT;
4867 4877
4868 sk = skb->sk;
4869 if (sk == NULL) { 4878 if (sk == NULL) {
4870 /* Without an associated socket the packet is either coming 4879 /* Without an associated socket the packet is either coming
4871 * from the kernel or it is being forwarded; check the packet 4880 * from the kernel or it is being forwarded; check the packet
@@ -4893,6 +4902,25 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4893 struct sk_security_struct *sksec = sk->sk_security; 4902 struct sk_security_struct *sksec = sk->sk_security;
4894 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) 4903 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4895 return NF_DROP; 4904 return NF_DROP;
4905 /* At this point, if the returned skb peerlbl is SECSID_NULL
4906 * and the packet has been through at least one XFRM
4907 * transformation then we must be dealing with the "final"
4908 * form of labeled IPsec packet; since we've already applied
4909 * all of our access controls on this packet we can safely
4910 * pass the packet. */
4911 if (skb_sid == SECSID_NULL) {
4912 switch (family) {
4913 case PF_INET:
4914 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4915 return NF_ACCEPT;
4916 break;
4917 case PF_INET6:
4918 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4919 return NF_ACCEPT;
4920 default:
4921 return NF_DROP_ERR(-ECONNREFUSED);
4922 }
4923 }
4896 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) 4924 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4897 return NF_DROP; 4925 return NF_DROP;
4898 secmark_perm = PACKET__SEND; 4926 secmark_perm = PACKET__SEND;