mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: WARN if skb_checksum_help() is called on skb requiring segmentation
skb_checksum_help() has never done anything useful with skbs that require segmentation. Setting skb->ip_summed = CHECKSUM_NONE makes them invalid and provokes a later WARNing in skb_gso_segment(). Passing such an skb to skb_checksum_help() indicates a bug, so we should warn about it immediately. Move the warning from skb_gso_segment() into a shared function, and add gso_type and gso_size to it. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									4144cb2ade
								
							
						
					
					
						commit
						36c9247449
					
				
					 1 changed files with 19 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -1887,6 +1887,22 @@ void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
 | 
			
		|||
EXPORT_SYMBOL(skb_set_dev);
 | 
			
		||||
#endif /* CONFIG_NET_NS */
 | 
			
		||||
 | 
			
		||||
static void skb_warn_bad_offload(const struct sk_buff *skb)
 | 
			
		||||
{
 | 
			
		||||
	struct net_device *dev = skb->dev;
 | 
			
		||||
	const char *driver = "";
 | 
			
		||||
 | 
			
		||||
	if (dev && dev->dev.parent)
 | 
			
		||||
		driver = dev_driver_string(dev->dev.parent);
 | 
			
		||||
 | 
			
		||||
	WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d gso_size=%d "
 | 
			
		||||
	     "gso_type=%d ip_summed=%d\n",
 | 
			
		||||
	     driver, dev ? &dev->features : NULL,
 | 
			
		||||
	     skb->sk ? &skb->sk->sk_route_caps : NULL,
 | 
			
		||||
	     skb->len, skb->data_len, skb_shinfo(skb)->gso_size,
 | 
			
		||||
	     skb_shinfo(skb)->gso_type, skb->ip_summed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Invalidate hardware checksum when packet is to be mangled, and
 | 
			
		||||
 * complete checksum manually on outgoing path.
 | 
			
		||||
| 
						 | 
				
			
			@ -1900,8 +1916,8 @@ int skb_checksum_help(struct sk_buff *skb)
 | 
			
		|||
		goto out_set_summed;
 | 
			
		||||
 | 
			
		||||
	if (unlikely(skb_shinfo(skb)->gso_size)) {
 | 
			
		||||
		/* Let GSO fix up the checksum. */
 | 
			
		||||
		goto out_set_summed;
 | 
			
		||||
		skb_warn_bad_offload(skb);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	offset = skb_checksum_start_offset(skb);
 | 
			
		||||
| 
						 | 
				
			
			@ -1961,16 +1977,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
 | 
			
		|||
	__skb_pull(skb, skb->mac_len);
 | 
			
		||||
 | 
			
		||||
	if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
 | 
			
		||||
		struct net_device *dev = skb->dev;
 | 
			
		||||
		const char *driver = "";
 | 
			
		||||
 | 
			
		||||
		if (dev && dev->dev.parent)
 | 
			
		||||
			driver = dev_driver_string(dev->dev.parent);
 | 
			
		||||
 | 
			
		||||
		WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d ip_summed=%d\n",
 | 
			
		||||
		     driver, dev ? &dev->features : NULL,
 | 
			
		||||
		     skb->sk ? &skb->sk->sk_route_caps : NULL,
 | 
			
		||||
		     skb->len, skb->data_len, skb->ip_summed);
 | 
			
		||||
		skb_warn_bad_offload(skb);
 | 
			
		||||
 | 
			
		||||
		if (skb_header_cloned(skb) &&
 | 
			
		||||
		    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue