diff options
Diffstat (limited to 'net/core/skbuff.c')
| -rw-r--r-- | net/core/skbuff.c | 16 | 
1 files changed, 10 insertions, 6 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2828f6d5ba89..e18184ffa9c3 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4853,7 +4853,7 @@ static int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate)  	if (err < 0)  		goto out; -	if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF)) +	if (ip_is_fragment(ip_hdr(skb)))  		fragment = true;  	off = ip_hdrlen(skb); @@ -5418,8 +5418,8 @@ struct sk_buff *skb_vlan_untag(struct sk_buff *skb)  	skb = skb_share_check(skb, GFP_ATOMIC);  	if (unlikely(!skb))  		goto err_free; - -	if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) +	/* We may access the two bytes after vlan_hdr in vlan_set_encap_proto(). */ +	if (unlikely(!pskb_may_pull(skb, VLAN_HLEN + sizeof(unsigned short))))  		goto err_free;  	vhdr = (struct vlan_hdr *)skb->data; @@ -5987,9 +5987,13 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,  	if (skb_has_frag_list(skb))  		skb_clone_fraglist(skb); -	if (k == 0) { -		/* split line is in frag list */ -		pskb_carve_frag_list(skb, shinfo, off - pos, gfp_mask); +	/* split line is in frag list */ +	if (k == 0 && pskb_carve_frag_list(skb, shinfo, off - pos, gfp_mask)) { +		/* skb_frag_unref() is not needed here as shinfo->nr_frags = 0. */ +		if (skb_has_frag_list(skb)) +			kfree_skb_list(skb_shinfo(skb)->frag_list); +		kfree(data); +		return -ENOMEM;  	}  	skb_release_data(skb);  |