diff options
Diffstat (limited to 'net/core/skbuff.c')
| -rw-r--r-- | net/core/skbuff.c | 23 | 
1 files changed, 13 insertions, 10 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b8afefe6f6b6..e18184ffa9c3 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3758,7 +3758,6 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,  	int err = -ENOMEM;  	int i = 0;  	int pos; -	int dummy;  	if (list_skb && !list_skb->head_frag && skb_headlen(list_skb) &&  	    (skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY)) { @@ -3780,7 +3779,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,  	}  	__skb_push(head_skb, doffset); -	proto = skb_network_protocol(head_skb, &dummy); +	proto = skb_network_protocol(head_skb, NULL);  	if (unlikely(!proto))  		return ERR_PTR(-EINVAL); @@ -4413,7 +4412,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)  	 * at the moment even if they are anonymous).  	 */  	if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) && -	    __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL) +	    !__pskb_pull_tail(skb, __skb_pagelen(skb)))  		return -ENOMEM;  	/* Easy case. Most of packets will go this way. */ @@ -4692,7 +4691,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,  		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&  		    sk->sk_protocol == IPPROTO_TCP &&  		    sk->sk_type == SOCK_STREAM) { -			skb = tcp_get_timestamping_opt_stats(sk); +			skb = tcp_get_timestamping_opt_stats(sk, orig_skb);  			opt_stats = true;  		} else  #endif @@ -4854,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); @@ -5419,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; @@ -5988,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);  | 
