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

Configure Feed

Select the types of activity you want to include in your feed.

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>

+38 -10
+38 -10
security/selinux/hooks.c
··· 4850 4850 * as fast and as clean as possible. */ 4851 4851 if (!selinux_policycap_netpeer) 4852 4852 return selinux_ip_postroute_compat(skb, ifindex, family); 4853 - #ifdef CONFIG_XFRM 4854 - /* 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 4856 - * since we'll have another chance to perform access control checks 4857 - * when the packet is on it's final way out. 4858 - * NOTE: there appear to be some IPv6 multicast cases where skb->dst 4859 - * is NULL, in this case go ahead and apply access control. */ 4860 - if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) 4861 - return NF_ACCEPT; 4862 - #endif 4853 + 4863 4854 secmark_active = selinux_secmark_enabled(); 4864 4855 peerlbl_active = selinux_peerlbl_enabled(); 4865 4856 if (!secmark_active && !peerlbl_active) 4866 4857 return NF_ACCEPT; 4867 4858 4868 4859 sk = skb->sk; 4860 + 4861 + #ifdef CONFIG_XFRM 4862 + /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4863 + * packet transformation so allow the packet to pass without any checks 4864 + * since we'll have another chance to perform access control checks 4865 + * when the packet is on it's final way out. 4866 + * NOTE: there appear to be some IPv6 multicast cases where skb->dst 4867 + * is NULL, in this case go ahead and apply access control. 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)) 4875 + return NF_ACCEPT; 4876 + #endif 4877 + 4869 4878 if (sk == NULL) { 4870 4879 /* Without an associated socket the packet is either coming 4871 4880 * from the kernel or it is being forwarded; check the packet ··· 4902 4893 struct sk_security_struct *sksec = sk->sk_security; 4903 4894 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) 4904 4895 return NF_DROP; 4896 + /* At this point, if the returned skb peerlbl is SECSID_NULL 4897 + * and the packet has been through at least one XFRM 4898 + * transformation then we must be dealing with the "final" 4899 + * form of labeled IPsec packet; since we've already applied 4900 + * all of our access controls on this packet we can safely 4901 + * pass the packet. */ 4902 + if (skb_sid == SECSID_NULL) { 4903 + switch (family) { 4904 + case PF_INET: 4905 + if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) 4906 + return NF_ACCEPT; 4907 + break; 4908 + case PF_INET6: 4909 + if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) 4910 + return NF_ACCEPT; 4911 + default: 4912 + return NF_DROP_ERR(-ECONNREFUSED); 4913 + } 4914 + } 4905 4915 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) 4906 4916 return NF_DROP; 4907 4917 secmark_perm = PACKET__SEND;