aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorthomas.zeitlhofer+lkml@ze-it.at <thomas.zeitlhofer+lkml@ze-it.at>2016-09-07 14:40:38 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2016-09-09 03:02:08 -0400
commit1fb81e09d487656aa23f2acb1232c7f56b4c2367 (patch)
tree72a7c89c15f827148d5eab8a1136aa565a7f4988 /net/ipv4
parent2f30ea5090cbc57ea573cdc66421264b3de3fb0a (diff)
vti: use right inner_mode for inbound inter address family policy checks
In case of inter address family tunneling (IPv6 over vti4 or IPv4 over vti6), the inbound policy checks in vti_rcv_cb() and vti6_rcv_cb() are using the wrong address family. As a result, all inbound inter address family traffic is dropped. Use the xfrm_ip2inner_mode() helper, as done in xfrm_input() (i.e., also increment LINUX_MIB_XFRMINSTATEMODEERROR in case of error), to select the inner_mode that contains the right address family for the inbound policy checks. Signed-off-by: Thomas Zeitlhofer <thomas.zeitlhofer+lkml@ze-it.at> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ip_vti.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index cc701fa70b12..5d7944f394d9 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -88,6 +88,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
88 struct net_device *dev; 88 struct net_device *dev;
89 struct pcpu_sw_netstats *tstats; 89 struct pcpu_sw_netstats *tstats;
90 struct xfrm_state *x; 90 struct xfrm_state *x;
91 struct xfrm_mode *inner_mode;
91 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; 92 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
92 u32 orig_mark = skb->mark; 93 u32 orig_mark = skb->mark;
93 int ret; 94 int ret;
@@ -105,7 +106,19 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
105 } 106 }
106 107
107 x = xfrm_input_state(skb); 108 x = xfrm_input_state(skb);
108 family = x->inner_mode->afinfo->family; 109
110 inner_mode = x->inner_mode;
111
112 if (x->sel.family == AF_UNSPEC) {
113 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
114 if (inner_mode == NULL) {
115 XFRM_INC_STATS(dev_net(skb->dev),
116 LINUX_MIB_XFRMINSTATEMODEERROR);
117 return -EINVAL;
118 }
119 }
120
121 family = inner_mode->afinfo->family;
109 122
110 skb->mark = be32_to_cpu(tunnel->parms.i_key); 123 skb->mark = be32_to_cpu(tunnel->parms.i_key);
111 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); 124 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);