summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2013-12-09 16:11:53 -0500
committerPaul Moore <pmoore@redhat.com>2013-12-10 14:50:25 -0500
commit5c6c26813a209e7075baf908e3ad81c1a9d389e8 (patch)
tree6df3b20fae12cdba5e0deb254b9df2b933983506 /security/selinux
parent5b67c493248059909d7e0ff646d8475306669b27 (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/selinux')
-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 95cb1345257d..a98228e7b91d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4846,22 +4846,31 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4846 * as fast and as clean as possible. */ 4846 * as fast and as clean as possible. */
4847 if (!selinux_policycap_netpeer) 4847 if (!selinux_policycap_netpeer)
4848 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
4849#ifdef CONFIG_XFRM 4857#ifdef CONFIG_XFRM
4850 /* 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
4851 * packet transformation so allow the packet to pass without any checks 4859 * packet transformation so allow the packet to pass without any checks
4852 * since we'll have another chance to perform access control checks 4860 * since we'll have another chance to perform access control checks
4853 * when the packet is on it's final way out. 4861 * when the packet is on it's final way out.
4854 * 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
4855 * is NULL, in this case go ahead and apply access control. */ 4863 * is NULL, in this case go ahead and apply access control.
4856 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))
4857 return NF_ACCEPT; 4871 return NF_ACCEPT;
4858#endif 4872#endif
4859 secmark_active = selinux_secmark_enabled();
4860 peerlbl_active = selinux_peerlbl_enabled();
4861 if (!secmark_active && !peerlbl_active)
4862 return NF_ACCEPT;
4863 4873
4864 sk = skb->sk;
4865 if (sk == NULL) { 4874 if (sk == NULL) {
4866 /* Without an associated socket the packet is either coming 4875 /* Without an associated socket the packet is either coming
4867 * from the kernel or it is being forwarded; check the packet 4876 * from the kernel or it is being forwarded; check the packet
@@ -4889,6 +4898,25 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4889 struct sk_security_struct *sksec = sk->sk_security; 4898 struct sk_security_struct *sksec = sk->sk_security;
4890 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) 4899 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4891 return NF_DROP; 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 }
4892 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) 4920 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4893 return NF_DROP; 4921 return NF_DROP;
4894 secmark_perm = PACKET__SEND; 4922 secmark_perm = PACKET__SEND;