Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3fa624e authored by Willem de Bruijn's avatar Willem de Bruijn Committed by Greg Kroah-Hartman
Browse files

udp: with udp_segment release on error path



[ Upstream commit 0f149c9fec3cd720628ecde83bfc6f64c1e7dcb6 ]

Failure __ip_append_data triggers udp_flush_pending_frames, but these
tests happen later. The skb must be freed directly.

Fixes: bec1f6f6 ("udp: generate gso with UDP_SEGMENT")
Reported-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 84bf7430
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -785,15 +785,23 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
		const int hlen = skb_network_header_len(skb) +
		const int hlen = skb_network_header_len(skb) +
				 sizeof(struct udphdr);
				 sizeof(struct udphdr);


		if (hlen + cork->gso_size > cork->fragsize)
		if (hlen + cork->gso_size > cork->fragsize) {
			kfree_skb(skb);
			return -EINVAL;
			return -EINVAL;
		if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
		}
		if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
			kfree_skb(skb);
			return -EINVAL;
			return -EINVAL;
		if (sk->sk_no_check_tx)
		}
		if (sk->sk_no_check_tx) {
			kfree_skb(skb);
			return -EINVAL;
			return -EINVAL;
		}
		if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
		if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
		    dst_xfrm(skb_dst(skb)))
		    dst_xfrm(skb_dst(skb))) {
			kfree_skb(skb);
			return -EIO;
			return -EIO;
		}


		skb_shinfo(skb)->gso_size = cork->gso_size;
		skb_shinfo(skb)->gso_size = cork->gso_size;
		skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
		skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
+12 −4
Original line number Original line Diff line number Diff line
@@ -1056,15 +1056,23 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
		const int hlen = skb_network_header_len(skb) +
		const int hlen = skb_network_header_len(skb) +
				 sizeof(struct udphdr);
				 sizeof(struct udphdr);


		if (hlen + cork->gso_size > cork->fragsize)
		if (hlen + cork->gso_size > cork->fragsize) {
			kfree_skb(skb);
			return -EINVAL;
			return -EINVAL;
		if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
		}
		if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
			kfree_skb(skb);
			return -EINVAL;
			return -EINVAL;
		if (udp_sk(sk)->no_check6_tx)
		}
		if (udp_sk(sk)->no_check6_tx) {
			kfree_skb(skb);
			return -EINVAL;
			return -EINVAL;
		}
		if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
		if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
		    dst_xfrm(skb_dst(skb)))
		    dst_xfrm(skb_dst(skb))) {
			kfree_skb(skb);
			return -EIO;
			return -EIO;
		}


		skb_shinfo(skb)->gso_size = cork->gso_size;
		skb_shinfo(skb)->gso_size = cork->gso_size;
		skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
		skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;