forked from mirrors/linux
		
	gro: ensure frag0 meets IP header alignment
After commit0f6925b3e8("virtio_net: Do not pull payload in skb->head") Guenter Roeck reported one failure in his tests using sh architecture. After much debugging, we have been able to spot silent unaligned accesses in inet_gro_receive() The issue at hand is that upper networking stacks assume their header is word-aligned. Low level drivers are supposed to reserve NET_IP_ALIGN bytes before the Ethernet header to make that happen. This patch hardens skb_gro_reset_offset() to not allow frag0 fast-path if the fragment is not properly aligned. Some arches like x86, arm64 and powerpc do not care and define NET_IP_ALIGN as 0, this extra check will be a NOP for them. Note that if frag0 is not used, GRO will call pskb_may_pull() as many times as needed to pull network and transport headers. Fixes:0f6925b3e8("virtio_net: Do not pull payload in skb->head") Fixes:78a478d0ef("gro: Inline skb_gro_header and cache frag0 virtual address") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Guenter Roeck <linux@roeck-us.net> Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Jason Wang <jasowang@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									b166a20b07
								
							
						
					
					
						commit
						38ec4944b5
					
				
					 1 changed files with 2 additions and 1 deletions
				
			
		| 
						 | 
					@ -5924,7 +5924,8 @@ static void skb_gro_reset_offset(struct sk_buff *skb)
 | 
				
			||||||
	NAPI_GRO_CB(skb)->frag0_len = 0;
 | 
						NAPI_GRO_CB(skb)->frag0_len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!skb_headlen(skb) && pinfo->nr_frags &&
 | 
						if (!skb_headlen(skb) && pinfo->nr_frags &&
 | 
				
			||||||
	    !PageHighMem(skb_frag_page(frag0))) {
 | 
						    !PageHighMem(skb_frag_page(frag0)) &&
 | 
				
			||||||
 | 
						    (!NET_IP_ALIGN || !(skb_frag_off(frag0) & 3))) {
 | 
				
			||||||
		NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
 | 
							NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
 | 
				
			||||||
		NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
 | 
							NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
 | 
				
			||||||
						    skb_frag_size(frag0),
 | 
											    skb_frag_size(frag0),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue