forked from mirrors/linux
		
	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: 2bd82484bb ("xps: fix xps for stacked devices")
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									c8a4d29988
								
							
						
					
					
						commit
						c29390c6df
					
				
					 4 changed files with 10 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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)
 | 
			
		|||
	skb->ignore_df = 0;
 | 
			
		||||
	skb_dst_drop(skb);
 | 
			
		||||
	skb->mark = 0;
 | 
			
		||||
	skb->sender_cpu = 0;
 | 
			
		||||
	skb_sender_cpu_clear(skb);
 | 
			
		||||
	skb_init_secmark(skb);
 | 
			
		||||
	secpath_reset(skb);
 | 
			
		||||
	nf_reset(skb);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,7 @@ static int ip_forward_finish(struct sk_buff *skb)
 | 
			
		|||
	if (unlikely(opt->optlen))
 | 
			
		||||
		ip_forward_options(skb);
 | 
			
		||||
 | 
			
		||||
	skb_sender_cpu_clear(skb);
 | 
			
		||||
	return dst_output(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)
 | 
			
		||||
{
 | 
			
		||||
	skb_sender_cpu_clear(skb);
 | 
			
		||||
	return dst_output(skb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue