From: Joshua Washington <joshwash@google.com>
To: netdev@vger.kernel.org
Cc: Joshua Washington <joshwash@google.com>,
Harshitha Ramamurthy <hramamurthy@google.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Jesper Dangaard Brouer <hawk@kernel.org>,
John Fastabend <john.fastabend@gmail.com>,
Stanislav Fomichev <sdf@fomichev.me>,
Jordan Rhee <jordanrhee@google.com>,
Willem de Bruijn <willemb@google.com>,
Tim Hostetler <thostet@google.com>,
Ankit Garg <nktgrg@google.com>,
Eddie Phillips <eddiephillips@google.com>,
Praveen Kaligineedi <pkaligineedi@google.com>,
Jeroen de Borst <jeroendb@google.com>,
linux-kernel@vger.kernel.org, bpf@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH net v2 9/9] gve: prevent XDP frame leak and corruption during DQO TX cleanup
Date: Tue, 22 Sep 2026 12:45:33 -0700 [thread overview]
Message-ID: <20260922194533.631387-10-joshwash@google.com> (raw)
In-Reply-To: <20260922194533.631387-1-joshwash@google.com>
From: Eddie Phillips <eddiephillips@google.com>
When tearing down a DQO TX ring or processing miss completions,
pending packets were assumed to be SKBs. If an XDP frame was pending
during cleanup or timeout, cur_state->skb was accessed on an xdpf
union pointer or the XDP frame was leaked without calling
xdp_return_frame().
Refactor gve_tx_clean_pending_packets(), gve_handle_miss_completion(),
and remove_miss_completions() to switch on pending_packet->type.
Fixes: d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ RDA")
Cc: stable@vger.kernel.org
Signed-off-by: Eddie Phillips <eddiephillips@google.com>
Signed-off-by: Joshua Washington <joshwash@google.com>
---
v2:
- Newly introduced.
---
drivers/net/ethernet/google/gve/gve_tx_dqo.c | 155 +++++++++++++------
1 file changed, 104 insertions(+), 51 deletions(-)
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index 78f946ae7264..e8481b993beb 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -186,6 +186,49 @@ static void gve_unmap_packet(struct device *dev,
pkt->num_bufs = 0;
}
+static struct gve_tx_pending_packet_dqo *
+gve_xsk_reorder_queue_head(struct gve_tx_ring *tx)
+{
+ u32 head = tx->dqo_compl.xsk_reorder_queue_head;
+
+ if (head == tx->dqo_compl.xsk_reorder_queue_tail) {
+ tx->dqo_compl.xsk_reorder_queue_tail =
+ atomic_read_acquire(&tx->dqo_tx.xsk_reorder_queue_tail);
+
+ if (head == tx->dqo_compl.xsk_reorder_queue_tail)
+ return NULL;
+ }
+
+ return &tx->dqo.pending_packets[tx->dqo.xsk_reorder_queue[head]];
+}
+
+static void gve_xsk_reorder_queue_pop_dqo(struct gve_tx_ring *tx)
+{
+ tx->dqo_compl.xsk_reorder_queue_head++;
+ tx->dqo_compl.xsk_reorder_queue_head &= tx->dqo.complq_mask;
+}
+
+static void gve_tx_process_xsk_completions(struct gve_tx_ring *tx)
+{
+ u32 num_xsks = 0;
+
+ while (true) {
+ struct gve_tx_pending_packet_dqo *pending_packet =
+ gve_xsk_reorder_queue_head(tx);
+
+ if (!pending_packet ||
+ pending_packet->state != GVE_PACKET_STATE_XSK_COMPLETE)
+ break;
+
+ num_xsks++;
+ gve_xsk_reorder_queue_pop_dqo(tx);
+ gve_free_pending_packet(tx, pending_packet);
+ }
+
+ if (num_xsks)
+ xsk_tx_completed(tx->xsk_pool, num_xsks);
+}
+
/* gve_tx_free_desc - Cleans up all pending tx requests and buffers.
*/
static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx)
@@ -201,11 +244,30 @@ static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx)
else
gve_unmap_packet(tx->dev, cur_state);
- if (cur_state->skb) {
- dev_consume_skb_any(cur_state->skb);
- cur_state->skb = NULL;
+ switch (cur_state->type) {
+ case GVE_TX_PENDING_PACKET_DQO_SKB:
+ if (cur_state->skb) {
+ dev_consume_skb_any(cur_state->skb);
+ cur_state->skb = NULL;
+ }
+ break;
+ case GVE_TX_PENDING_PACKET_DQO_XDP_FRAME:
+ if (cur_state->xdpf) {
+ xdp_return_frame(cur_state->xdpf);
+ cur_state->xdpf = NULL;
+ }
+ break;
+ case GVE_TX_PENDING_PACKET_DQO_XSK:
+ cur_state->state = GVE_PACKET_STATE_XSK_COMPLETE;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
}
}
+
+ if (tx->xsk_pool)
+ gve_tx_process_xsk_completions(tx);
}
static void gve_tx_init_ring_state_dqo(struct gve_tx_ring *tx)
@@ -1089,28 +1151,6 @@ static void gve_xsk_reorder_queue_push_dqo(struct gve_tx_ring *tx,
atomic_set_release(&tx->dqo_tx.xsk_reorder_queue_tail, tail);
}
-static struct gve_tx_pending_packet_dqo *
-gve_xsk_reorder_queue_head(struct gve_tx_ring *tx)
-{
- u32 head = tx->dqo_compl.xsk_reorder_queue_head;
-
- if (head == tx->dqo_compl.xsk_reorder_queue_tail) {
- tx->dqo_compl.xsk_reorder_queue_tail =
- atomic_read_acquire(&tx->dqo_tx.xsk_reorder_queue_tail);
-
- if (head == tx->dqo_compl.xsk_reorder_queue_tail)
- return NULL;
- }
-
- return &tx->dqo.pending_packets[tx->dqo.xsk_reorder_queue[head]];
-}
-
-static void gve_xsk_reorder_queue_pop_dqo(struct gve_tx_ring *tx)
-{
- tx->dqo_compl.xsk_reorder_queue_head++;
- tx->dqo_compl.xsk_reorder_queue_head &= tx->dqo.complq_mask;
-}
-
/* Transmit a given skb and ring the doorbell. */
netdev_tx_t gve_tx_dqo(struct sk_buff *skb, struct net_device *dev)
{
@@ -1347,8 +1387,25 @@ static void gve_handle_miss_completion(struct gve_priv *priv,
secs_to_jiffies(GVE_REINJECT_COMPL_TIMEOUT);
add_to_list(tx, &tx->dqo_compl.miss_completions, pending_packet);
- *bytes += pending_packet->skb->len;
- (*pkts)++;
+ switch (pending_packet->type) {
+ case GVE_TX_PENDING_PACKET_DQO_SKB:
+ if (pending_packet->skb) {
+ *bytes += pending_packet->skb->len;
+ (*pkts)++;
+ }
+ break;
+ case GVE_TX_PENDING_PACKET_DQO_XDP_FRAME:
+ if (pending_packet->xdpf) {
+ *bytes += pending_packet->xdpf->len;
+ (*pkts)++;
+ }
+ break;
+ case GVE_TX_PENDING_PACKET_DQO_XSK:
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
}
static void remove_miss_completions(struct gve_priv *priv,
@@ -1377,9 +1434,26 @@ static void remove_miss_completions(struct gve_priv *priv,
else
gve_unmap_packet(tx->dev, pending_packet);
- /* This indicates the packet was dropped. */
- dev_kfree_skb_any(pending_packet->skb);
- pending_packet->skb = NULL;
+ switch (pending_packet->type) {
+ case GVE_TX_PENDING_PACKET_DQO_SKB:
+ if (pending_packet->skb) {
+ /* This indicates the packet was dropped. */
+ dev_kfree_skb_any(pending_packet->skb);
+ pending_packet->skb = NULL;
+ }
+ break;
+ case GVE_TX_PENDING_PACKET_DQO_XDP_FRAME:
+ if (pending_packet->xdpf) {
+ xdp_return_frame(pending_packet->xdpf);
+ pending_packet->xdpf = NULL;
+ }
+ break;
+ case GVE_TX_PENDING_PACKET_DQO_XSK:
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
u64_stats_update_begin(&tx->statss);
tx->dropped_pkt++;
@@ -1426,27 +1500,6 @@ static void remove_timed_out_completions(struct gve_priv *priv,
}
}
-static void gve_tx_process_xsk_completions(struct gve_tx_ring *tx)
-{
- u32 num_xsks = 0;
-
- while (true) {
- struct gve_tx_pending_packet_dqo *pending_packet =
- gve_xsk_reorder_queue_head(tx);
-
- if (!pending_packet ||
- pending_packet->state != GVE_PACKET_STATE_XSK_COMPLETE)
- break;
-
- num_xsks++;
- gve_xsk_reorder_queue_pop_dqo(tx);
- gve_free_pending_packet(tx, pending_packet);
- }
-
- if (num_xsks)
- xsk_tx_completed(tx->xsk_pool, num_xsks);
-}
-
int gve_clean_tx_done_dqo(struct gve_priv *priv, struct gve_tx_ring *tx,
struct napi_struct *napi)
{
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-22 19:45 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 19:45 [PATCH net v2 0/9] gve: various XDP fixes Joshua Washington
2026-09-22 19:45 ` [PATCH net v2 1/9] gve: increment work_done for XDP and error packets Joshua Washington
2026-09-24 10:46 ` netdev-bot+sashiko
2026-09-22 19:45 ` [PATCH net v2 2/9] gve: fix XSK buffer leak when rings are stopped Joshua Washington
2026-09-22 19:45 ` [PATCH net v2 3/9] gve: fix XSK buffer leak on error descriptor Joshua Washington
2026-09-22 19:45 ` [PATCH net v2 4/9] gve: don't register xsk pool on pre-existing queues in RDA mode Joshua Washington
2026-09-24 10:46 ` netdev-bot+sashiko
2026-09-22 19:45 ` [PATCH net v2 5/9] gve: fix napi_disable deadlock when attempting to disable XSK pools Joshua Washington
2026-09-22 19:45 ` [PATCH net v2 6/9] gve: fix NULL dereference from premature XSK pool DMA unmap Joshua Washington
2026-09-24 10:46 ` netdev-bot+sashiko
2026-09-22 19:45 ` [PATCH net v2 7/9] gve: disable NAPI when registering XSK pools in QPL mode Joshua Washington
2026-09-23 19:45 ` sashiko-bot
2026-09-24 10:46 ` netdev-bot+sashiko
2026-09-22 19:45 ` [PATCH net v2 8/9] gve: ensure XDP mem model is registered when disabling XSK pools Joshua Washington
2026-09-23 19:45 ` sashiko-bot
2026-09-24 10:46 ` netdev-bot+sashiko
2026-09-22 19:45 ` Joshua Washington [this message]
2026-09-24 10:46 ` [PATCH net v2 9/9] gve: prevent XDP frame leak and corruption during DQO TX cleanup netdev-bot+sashiko
2026-09-29 17:48 ` [PATCH net v2 0/9] gve: various XDP fixes Joshua Washington
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260922194533.631387-10-joshwash@google.com \
--to=joshwash@google.com \
--cc=andrew+netdev@lunn.ch \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=eddiephillips@google.com \
--cc=edumazet@google.com \
--cc=hawk@kernel.org \
--cc=hramamurthy@google.com \
--cc=jeroendb@google.com \
--cc=john.fastabend@gmail.com \
--cc=jordanrhee@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nktgrg@google.com \
--cc=pabeni@redhat.com \
--cc=pkaligineedi@google.com \
--cc=sdf@fomichev.me \
--cc=stable@vger.kernel.org \
--cc=thostet@google.com \
--cc=willemb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.