diff options
| -rw-r--r-- | security/selinux/hooks.c | 42 |
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; |
