Commit c29390c6 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarJohn <jw@nuclearfallout.net>
Bisected-by: default avatarJohn <jw@nuclearfallout.net>
Fixes: 2bd82484 ("xps: fix xps for stacked devices")
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c8a4d299
...@@ -948,6 +948,13 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) ...@@ -948,6 +948,13 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
to->l4_hash = from->l4_hash; to->l4_hash = from->l4_hash;
}; };
static inline void skb_sender_cpu_clear(struct sk_buff *skb)
{
#ifdef CONFIG_XPS
skb->sender_cpu = 0;
#endif
}
#ifdef NET_SKBUFF_DATA_USES_OFFSET #ifdef NET_SKBUFF_DATA_USES_OFFSET
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{ {
......
...@@ -4173,7 +4173,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) ...@@ -4173,7 +4173,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
skb->ignore_df = 0; skb->ignore_df = 0;
skb_dst_drop(skb); skb_dst_drop(skb);
skb->mark = 0; skb->mark = 0;
skb->sender_cpu = 0; skb_sender_cpu_clear(skb);
skb_init_secmark(skb); skb_init_secmark(skb);
secpath_reset(skb); secpath_reset(skb);
nf_reset(skb); nf_reset(skb);
......
...@@ -67,6 +67,7 @@ static int ip_forward_finish(struct sk_buff *skb) ...@@ -67,6 +67,7 @@ static int ip_forward_finish(struct sk_buff *skb)
if (unlikely(opt->optlen)) if (unlikely(opt->optlen))
ip_forward_options(skb); ip_forward_options(skb);
skb_sender_cpu_clear(skb);
return dst_output(skb); return dst_output(skb);
} }
......
...@@ -318,6 +318,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) ...@@ -318,6 +318,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
static inline int ip6_forward_finish(struct sk_buff *skb) static inline int ip6_forward_finish(struct sk_buff *skb)
{ {
skb_sender_cpu_clear(skb);
return dst_output(skb); return dst_output(skb);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment