xsk: Free skb when TX metadata options are invalid
[ Upstream commit0c0d0f42ff] When a new skb is allocated for transmitting an xsk descriptor, i.e., for every non-multibuf descriptor or the first frag of a multibuf descriptor, but the descriptor is later found to have invalid options set for the TX metadata, the new skb is never freed. This can leak skbs until the send buffer is full which makes sending more packets impossible. Fix this by freeing the skb in the error path if we are currently dealing with the first frag, i.e., an skb allocated in this iteration of xsk_build_skb. Fixes:48eb03dd26("xsk: Add TX timestamp and TX checksum offload support") Reported-by: Michal Schmidt <mschmidt@redhat.com> Signed-off-by: Felix Maurer <fmaurer@redhat.com> Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com> Acked-by: Stanislav Fomichev <sdf@fomichev.me> Acked-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://patch.msgid.link/edb9b00fb19e680dff5a3350cd7581c5927975a8.1731581697.git.fmaurer@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
7b277bd569
commit
d5d346deb6
+6
-5
@@ -675,6 +675,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,
|
||||
len = desc->len;
|
||||
|
||||
if (!skb) {
|
||||
first_frag = true;
|
||||
|
||||
hr = max(NET_SKB_PAD, L1_CACHE_ALIGN(dev->needed_headroom));
|
||||
tr = dev->needed_tailroom;
|
||||
skb = sock_alloc_send_skb(&xs->sk, hr + len + tr, 1, &err);
|
||||
@@ -685,12 +687,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,
|
||||
skb_put(skb, len);
|
||||
|
||||
err = skb_store_bits(skb, 0, buffer, len);
|
||||
if (unlikely(err)) {
|
||||
kfree_skb(skb);
|
||||
if (unlikely(err))
|
||||
goto free_err;
|
||||
}
|
||||
|
||||
first_frag = true;
|
||||
} else {
|
||||
int nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
struct page *page;
|
||||
@@ -758,6 +756,9 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,
|
||||
return skb;
|
||||
|
||||
free_err:
|
||||
if (first_frag && skb)
|
||||
kfree_skb(skb);
|
||||
|
||||
if (err == -EOVERFLOW) {
|
||||
/* Drop the packet */
|
||||
xsk_set_destructor_arg(xs->skb);
|
||||
|
||||
Reference in New Issue
Block a user