]>
Commit | Line | Data |
---|---|---|
a8360df2 GKH |
1 | From foo@baz Thu Jan 12 21:37:26 CET 2017 |
2 | From: David Ahern <dsa@cumulusnetworks.com> | |
3 | Date: Wed, 14 Dec 2016 14:31:11 -0800 | |
4 | Subject: net: vrf: Drop conntrack data after pass through VRF device on Tx | |
5 | ||
6 | From: David Ahern <dsa@cumulusnetworks.com> | |
7 | ||
8 | ||
9 | [ Upstream commit eb63ecc1706b3e094d0f57438b6c2067cfc299f2 ] | |
10 | ||
11 | Locally originated traffic in a VRF fails in the presence of a POSTROUTING | |
12 | rule. For example, | |
13 | ||
14 | $ iptables -t nat -A POSTROUTING -s 11.1.1.0/24 -j MASQUERADE | |
15 | $ ping -I red -c1 11.1.1.3 | |
16 | ping: Warning: source address might be selected on device other than red. | |
17 | PING 11.1.1.3 (11.1.1.3) from 11.1.1.2 red: 56(84) bytes of data. | |
18 | ping: sendmsg: Operation not permitted | |
19 | ||
20 | Worse, the above causes random corruption resulting in a panic in random | |
21 | places (I have not seen a consistent backtrace). | |
22 | ||
23 | Call nf_reset to drop the conntrack info following the pass through the | |
24 | VRF device. The nf_reset is needed on Tx but not Rx because of the order | |
25 | in which NF_HOOK's are hit: on Rx the VRF device is after the real ingress | |
26 | device and on Tx it is is before the real egress device. Connection | |
27 | tracking should be tied to the real egress device and not the VRF device. | |
28 | ||
29 | Fixes: 8f58336d3f78a ("net: Add ethernet header for pass through VRF device") | |
30 | Fixes: 35402e3136634 ("net: Add IPv6 support to VRF device") | |
31 | Signed-off-by: David Ahern <dsa@cumulusnetworks.com> | |
32 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
33 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
34 | --- | |
35 | drivers/net/vrf.c | 4 ++++ | |
36 | 1 file changed, 4 insertions(+) | |
37 | ||
38 | --- a/drivers/net/vrf.c | |
39 | +++ b/drivers/net/vrf.c | |
40 | @@ -371,6 +371,8 @@ static int vrf_finish_output6(struct net | |
41 | struct in6_addr *nexthop; | |
42 | int ret; | |
43 | ||
44 | + nf_reset(skb); | |
45 | + | |
46 | skb->protocol = htons(ETH_P_IPV6); | |
47 | skb->dev = dev; | |
48 | ||
49 | @@ -552,6 +554,8 @@ static int vrf_finish_output(struct net | |
50 | u32 nexthop; | |
51 | int ret = -EINVAL; | |
52 | ||
53 | + nf_reset(skb); | |
54 | + | |
55 | /* Be paranoid, rather than too clever. */ | |
56 | if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { | |
57 | struct sk_buff *skb2; |