aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-03-11 21:42:02 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-11 23:51:18 -0400
commitc29390c6dfeee0944ac6b5610ebbe403944378fc (patch)
treebefe951b043be948957abb1db65cee36dd7a379b /net
parentc8a4d29988edb0db9ee80669f2e5e21bd9f7e0d0 (diff)
xps: must clear sender_cpu before forwarding
John reported that my previous commit added a regression on his router. This is because sender_cpu & napi_id share a common location, so get_xps_queue() can see garbage and perform an out of bound access. We need to make sure sender_cpu is cleared before doing the transmit, otherwise any NIC busy poll enabled (skb_mark_napi_id()) can trigger this bug. Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: John <jw@nuclearfallout.net> Bisected-by: John <jw@nuclearfallout.net> Fixes: 2bd82484bb4c ("xps: fix xps for stacked devices") Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/ipv4/ip_forward.c1
-rw-r--r--net/ipv6/ip6_output.c1
3 files changed, 3 insertions, 1 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f80507823531..434e78e5254d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4173,7 +4173,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
4173 skb->ignore_df = 0; 4173 skb->ignore_df = 0;
4174 skb_dst_drop(skb); 4174 skb_dst_drop(skb);
4175 skb->mark = 0; 4175 skb->mark = 0;
4176 skb->sender_cpu = 0; 4176 skb_sender_cpu_clear(skb);
4177 skb_init_secmark(skb); 4177 skb_init_secmark(skb);
4178 secpath_reset(skb); 4178 secpath_reset(skb);
4179 nf_reset(skb); 4179 nf_reset(skb);
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 787b3c294ce6..d9bc28ac5d1b 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -67,6 +67,7 @@ static int ip_forward_finish(struct sk_buff *skb)
67 if (unlikely(opt->optlen)) 67 if (unlikely(opt->optlen))
68 ip_forward_options(skb); 68 ip_forward_options(skb);
69 69
70 skb_sender_cpu_clear(skb);
70 return dst_output(skb); 71 return dst_output(skb);
71} 72}
72 73
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 0a04a37305d5..7e80b61b51ff 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -318,6 +318,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
318 318
319static inline int ip6_forward_finish(struct sk_buff *skb) 319static inline int ip6_forward_finish(struct sk_buff *skb)
320{ 320{
321 skb_sender_cpu_clear(skb);
321 return dst_output(skb); 322 return dst_output(skb);
322} 323}
323 324