* [PATCH net v4 0/2] gve: fix RX page refcount overflow with the pagecnt bias
@ 2026-11-06 11:45 Amaan Cheval
2026-11-06 11:45 ` [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format Amaan Cheval
2026-11-06 11:45 ` [PATCH net v4 2/2] gve: fix RX page refcount overflow from the pagecnt bias Amaan Cheval
0 siblings, 2 replies; 7+ messages in thread
From: Amaan Cheval @ 2026-11-06 11:45 UTC (permalink / raw)
To: netdev
Cc: joshwash, hramamurthy, andrew+netdev, davem, edumazet, kuba,
pabeni, bcf, jordanrhee, przemyslaw.kitszel, maciej.fijalkowski,
pkaligineedi, maolson, csully, willemb, yangchun, npl,
awogbemila, shailend, nktgrg, maxyuan, bpf, john.fastabend, hawk,
sdf, daniel, ast, linux-kernel, stable, Amaan Cheval
gve's GQI and DQO-QPL RX paths bias every RX page's refcount to INT_MAX,
so a single get_page() from the stack, e.g. splice() of received data,
overflows it: splice/tee fail with EIO/EFAULT and GQI can reset the
NIC. Patch 2 lowers the bias to USHRT_MAX, as other drivers do.
With the smaller bias the driver gives up its last reference on a page
once every USHRT_MAX handoffs instead of once every INT_MAX, which is
only safe while every consumer holds its reference until the buffer is
recycled. That is not the case for an XDP_REDIRECT from DQO-QPL to an
AF_XDP socket in copy mode, a path the driver never meant to support:
commit d8a8ca14c937 dropped the queue_format check that used to refuse
it. Patch 1 restores that check for DQO-QPL, so patch 2 depends on it.
Trees before 6.17 still have the old check, so there patch 2 stands
alone.
Harshitha mentioned on v2 that Google would send a patch blocking XDP
on DQO-QPL; if one is already in flight I'm happy to drop patch 1 in
its favour.
v4:
- Add patch 1/2 blocking XDP on DQO-QPL (Sashiko).
- Say "overflow" instead of "headroom"; use USHRT_MAX directly instead
of a macro (Maciej).
- Say which trees need patch 1, for stable.
v3: https://lore.kernel.org/netdev/20261103090651.35399-1-amaan.cheval@gmail.com/
v2: https://lore.kernel.org/netdev/20261102112613.18334-1-amaan.cheval@gmail.com/
v1: https://lore.kernel.org/netdev/20261031173449.2439047-1-amaan.cheval@gmail.com/
Amaan Cheval (2):
gve: block XDP on the DQO-QPL queue format
gve: fix RX page refcount overflow from the pagecnt bias
drivers/net/ethernet/google/gve/gve.h | 2 +-
.../net/ethernet/google/gve/gve_buffer_mgmt_dqo.c | 4 ++--
drivers/net/ethernet/google/gve/gve_main.c | 6 ++++++
drivers/net/ethernet/google/gve/gve_rx.c | 8 ++++----
drivers/net/ethernet/google/gve/gve_utils.c | 12 ++++--------
drivers/net/ethernet/google/gve/gve_utils.h | 2 +-
6 files changed, 18 insertions(+), 16 deletions(-)
base-commit: 21f57ec673a1917547c808cfa81890485fffa03b
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format
2026-11-06 11:45 [PATCH net v4 0/2] gve: fix RX page refcount overflow with the pagecnt bias Amaan Cheval
@ 2026-11-06 11:45 ` Amaan Cheval
2026-11-07 3:13 ` Joshua Washington
2026-11-10 12:04 ` netdev-bot+sashiko
2026-11-06 11:45 ` [PATCH net v4 2/2] gve: fix RX page refcount overflow from the pagecnt bias Amaan Cheval
1 sibling, 2 replies; 7+ messages in thread
From: Amaan Cheval @ 2026-11-06 11:45 UTC (permalink / raw)
To: netdev
Cc: joshwash, hramamurthy, andrew+netdev, davem, edumazet, kuba,
pabeni, bcf, jordanrhee, przemyslaw.kitszel, maciej.fijalkowski,
pkaligineedi, maolson, csully, willemb, yangchun, npl,
awogbemila, shailend, nktgrg, maxyuan, bpf, john.fastabend, hawk,
sdf, daniel, ast, linux-kernel, stable, Amaan Cheval
Commit d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ
RDA") enabled XDP on DQO-RDA by dropping the queue_format check from
verify_xdp_configuration(), which until then refused every format but
GQI-QPL. Nothing replaced it for DQO-QPL: gve_set_netdev_xdp_features()
advertises no XDP features there and gve_xdp_xmit() rejects it, but the
core only checks that ndo_bpf exists, so a native XDP program, and an
AF_XDP socket on top of it, can still be attached on DQO-QPL.
The DQO-QPL RX path was never written for that. Its page accounting
assumes the driver keeps a reference of its own across every handoff:
gve_xdp_done_dqo() passes the buffer to xdp_do_redirect() and then
recycles it with gve_reuse_buffer(), so a redirect target that releases
the buffer synchronously, such as an AF_XDP socket in copy mode, can
drop the page's last reference when pagecnt_bias runs out. The page is
then freed while it is still DMA-mapped and registered in the QPL, and
the driver posts it back to the device.
Refuse XDP program setup on DQO-QPL in gve_verify_xdp_configuration(),
matching the features the driver advertises. A zero-copy XSK pool bind
is already refused by the core for the same reason, and a copy-mode
bind never reaches the driver and is harmless without a program.
Fixes: d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ RDA")
Cc: stable@vger.kernel.org
Signed-off-by: Amaan Cheval <amaan.cheval@gmail.com>
---
drivers/net/ethernet/google/gve/gve_main.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 2437cd8ba633..4e9e692a0ed0 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1723,6 +1723,12 @@ static int gve_verify_xdp_configuration(struct net_device *dev,
struct gve_priv *priv = netdev_priv(dev);
u16 max_xdp_mtu;
+ if (priv->queue_format == GVE_DQO_QPL_FORMAT) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "XDP is not supported in DQO QPL queue format.");
+ return -EOPNOTSUPP;
+ }
+
if (dev->features & NETIF_F_GRO_HW) {
NL_SET_ERR_MSG_MOD(extack,
"XDP is not supported when HW-GRO is on.");
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net v4 2/2] gve: fix RX page refcount overflow from the pagecnt bias
2026-11-06 11:45 [PATCH net v4 0/2] gve: fix RX page refcount overflow with the pagecnt bias Amaan Cheval
2026-11-06 11:45 ` [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format Amaan Cheval
@ 2026-11-06 11:45 ` Amaan Cheval
1 sibling, 0 replies; 7+ messages in thread
From: Amaan Cheval @ 2026-11-06 11:45 UTC (permalink / raw)
To: netdev
Cc: joshwash, hramamurthy, andrew+netdev, davem, edumazet, kuba,
pabeni, bcf, jordanrhee, przemyslaw.kitszel, maciej.fijalkowski,
pkaligineedi, maolson, csully, willemb, yangchun, npl,
awogbemila, shailend, nktgrg, maxyuan, bpf, john.fastabend, hawk,
sdf, daniel, ast, linux-kernel, stable, Amaan Cheval
gve's GQI and DQO-QPL RX paths set every RX page's refcount to INT_MAX and
hand references to the stack by decrementing page_info->pagecnt_bias, to
avoid an atomic op per packet. This leaves no room for anyone else: while
a fresh page's buffer sits in an skb its refcount is already INT_MAX, so a
single get_page() from the stack overflows it to negative.
splice() of received TCP data into a pipe takes such a reference, and the
onward splice into a socket then fails: skb_splice_from_iter() sees
page_count() < 1, sendpage_ok() fails and the send returns -EIO (since
commit 2e910b95329c ("net: Add a function to splice pages into an
skbuff for MSG_SPLICE_PAGES")). tee() of the pipe fails with -EFAULT via
try_get_page(). On GQI the reuse check gve_rx_can_recycle_buffer() also
sees page_count() < pagecnt_bias, WARNs and calls gve_schedule_reset(),
so a task that merely pins a fresh RX page (e.g. holds spliced data in
an undrained tee() pipe) can reset the NIC.
Use USHRT_MAX in a u16, as igb, igc, ixgbe, i40e and hns3 do: the bias
only has to make the per-packet atomic rare, so a small value keeps
page_count() far below INT_MAX however many references the stack takes.
Refill by adding a fixed batch and setting the bias to it, which keeps
the rule `references = page_count() - bias` intact.
Refilling at 0 hands the driver's last reference to the consumer once
every USHRT_MAX handoffs rather than once every INT_MAX, which is only
safe because every consumer on these paths holds its reference until
the driver has recycled the buffer. The previous patch keeps it that
way by blocking XDP on DQO-QPL, so this one depends on it. Trees before
6.17, without commit d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT
support for DQ RDA"), still refuse XDP on every format but GQI-QPL in
verify_xdp_configuration(), so there this patch stands alone.
Reproduced on gVNIC in GQI-QPL mode (GCE n2-standard-8, 6.12) and in
DQO-RDA mode (GCE c3-standard-8, 6.12, where DQO-RDA still uses the
bias) with the help of relay.py -- a small splice(2) TCP proxy --
relaying a download while the RX ring is refilled with fresh pages:
ethtool -G eth0 rx 512 && ethtool -G eth0 rx 1024 # fresh RX pages
./relay.py $HOST 8080 & # splice()s both ways
for i in $(seq 200); do curl -so /dev/null \
--connect-to $HOST:80:127.0.0.1:8080 http://$HOST/file; done
Most downloads failed with EIO before the fix (tee() with EFAULT) and
all completed after it. relay.py is at the Link below.
This bug was found and fixed with the help of an AI coding assistant
(Claude Code) over an interactive session; it read the driver and
splice/pipe code and ran the tests above.
Link: https://github.com/amaanc/kernel-bias
Fixes: 9b8dd5e5ea48 ("gve: DQO: Add RX path")
Fixes: 58401b2a46e7 ("gve: Add rx buffer pagecnt bias")
Fixes: 82fd151d38d9 ("gve: Reduce alloc and copy costs in the GQ rx path")
Cc: stable@vger.kernel.org
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
Tested-by: Harshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Amaan Cheval <amaan.cheval@gmail.com>
---
v4:
- Add patch 1/2, blocking XDP on DQO-QPL, which this fix depends on
(Sashiko). Harshitha said Google would send such a patch; I'm happy
to drop 1/2 in favour of theirs.
- Say "overflow" instead of "headroom" in the subject and the commit
message (Maciej).
- Use USHRT_MAX directly instead of a GVE_PAGECNT_BIAS macro, as the
other drivers do, and move its rationale next to the refill in
gve_dec_pagecnt_bias() (Maciej). No functional change.
- Added Reviewed-by from Maciej Fijalkowski.
- Say which trees need patch 1/2, for stable.
v3: https://lore.kernel.org/netdev/20261103090651.35399-1-amaan.cheval@gmail.com/
- Refill when the bias reaches 0 again, as in v1. DQO-QPL is not
supposed to support XDP at all, and it will be blocked explicitly in
a separate patch, so the v2 refill-at-1 change is not needed.
- Added Reviewed-by and Tested-by from Harshitha Ramamurthy.
v2: https://lore.kernel.org/netdev/20261102112613.18334-1-amaan.cheval@gmail.com/
- Refill when the bias reaches 1 instead of 0 so the driver keeps a
reference of its own across every handoff. At bias 0 a consumer that
returns its reference synchronously, such as an AF_XDP socket in copy
mode on an XDP_REDIRECT from DQO-QPL, freed a page still registered in
the QPL.
- Commit message: explain the refill point, drop the build notes.
- Re-tested on 6.12.113 (c3-standard-8, DQO-RDA, which still uses the
bias on 6.12): no EIO/EFAULT from splice/tee and no NIC reset after
applying the patch. DQO-QPL is untested; I have no access to that
hardware.
v1: https://lore.kernel.org/netdev/20261031173449.2439047-1-amaan.cheval@gmail.com/
Built allmodconfig W=1, no new warnings.
drivers/net/ethernet/google/gve/gve.h | 2 +-
.../net/ethernet/google/gve/gve_buffer_mgmt_dqo.c | 4 ++--
drivers/net/ethernet/google/gve/gve_rx.c | 8 ++++----
drivers/net/ethernet/google/gve/gve_utils.c | 12 ++++--------
drivers/net/ethernet/google/gve/gve_utils.h | 2 +-
5 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index b7ce6e8632db..18d7edbf4b3b 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -119,7 +119,7 @@ struct gve_rx_slot_page_info {
void *page_address;
u32 page_offset; /* offset to write to in page */
unsigned int buf_size;
- int pagecnt_bias; /* expected pagecnt if only the driver has a ref */
+ u16 pagecnt_bias; /* expected pagecnt if only the driver has a ref */
u16 pad; /* adjustment for rx padding */
u8 can_flip; /* tracks if the networking stack is using the page */
};
diff --git a/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c b/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
index 6880d1531ba5..52223baf0303 100644
--- a/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
@@ -149,8 +149,8 @@ int gve_alloc_qpl_page_dqo(struct gve_rx_ring *rx,
buf_state->last_single_ref_offset = 0;
/* The page already has 1 ref. */
- page_ref_add(buf_state->page_info.page, INT_MAX - 1);
- buf_state->page_info.pagecnt_bias = INT_MAX;
+ page_ref_add(buf_state->page_info.page, USHRT_MAX - 1);
+ buf_state->page_info.pagecnt_bias = USHRT_MAX;
return 0;
}
diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c
index 81ea800e66e9..3bed19866376 100644
--- a/drivers/net/ethernet/google/gve/gve_rx.c
+++ b/drivers/net/ethernet/google/gve/gve_rx.c
@@ -152,8 +152,8 @@ static void gve_setup_rx_buffer(struct gve_rx_ring *rx,
page_info->buf_size = rx->packet_buffer_size;
*slot_addr = cpu_to_be64(addr);
/* The page already has 1 ref */
- page_ref_add(page, INT_MAX - 1);
- page_info->pagecnt_bias = INT_MAX;
+ page_ref_add(page, USHRT_MAX - 1);
+ page_info->pagecnt_bias = USHRT_MAX;
}
static int gve_rx_alloc_buffer(struct gve_priv *priv, struct device *dev,
@@ -230,8 +230,8 @@ static int gve_rx_prefill_pages(struct gve_rx_ring *rx,
rx->qpl_copy_pool[j].buf_size = rx->packet_buffer_size;
/* The page already has 1 ref. */
- page_ref_add(page, INT_MAX - 1);
- rx->qpl_copy_pool[j].pagecnt_bias = INT_MAX;
+ page_ref_add(page, USHRT_MAX - 1);
+ rx->qpl_copy_pool[j].pagecnt_bias = USHRT_MAX;
}
}
diff --git a/drivers/net/ethernet/google/gve/gve_utils.c b/drivers/net/ethernet/google/gve/gve_utils.c
index caed38cd5f2b..930555ac8fe9 100644
--- a/drivers/net/ethernet/google/gve/gve_utils.c
+++ b/drivers/net/ethernet/google/gve/gve_utils.c
@@ -93,15 +93,11 @@ void gve_dec_pagecnt_bias(struct gve_rx_slot_page_info *page_info)
{
page_info->pagecnt_bias--;
if (page_info->pagecnt_bias == 0) {
- int pagecount = page_count(page_info->page);
-
- /* If we have run out of bias - set it back up to INT_MAX
- * minus the existing refs.
+ /* Out of bias: take another batch. USHRT_MAX keeps this rare
+ * while leaving page_count() far below INT_MAX.
*/
- page_info->pagecnt_bias = INT_MAX - pagecount;
-
- /* Set pagecount back up to max. */
- page_ref_add(page_info->page, INT_MAX - pagecount);
+ page_info->pagecnt_bias = USHRT_MAX;
+ page_ref_add(page_info->page, USHRT_MAX);
}
}
diff --git a/drivers/net/ethernet/google/gve/gve_utils.h b/drivers/net/ethernet/google/gve/gve_utils.h
index bf2e9a0adb36..c686142d37ea 100644
--- a/drivers/net/ethernet/google/gve/gve_utils.h
+++ b/drivers/net/ethernet/google/gve/gve_utils.h
@@ -25,7 +25,7 @@ struct sk_buff *gve_rx_copy_data(struct net_device *dev, struct napi_struct *nap
struct sk_buff *gve_rx_copy(struct net_device *dev, struct napi_struct *napi,
struct gve_rx_slot_page_info *page_info, u16 len);
-/* Decrement pagecnt_bias. Set it back to INT_MAX if it reached zero. */
+/* Decrement pagecnt_bias. Top it up by USHRT_MAX if it reached zero. */
void gve_dec_pagecnt_bias(struct gve_rx_slot_page_info *page_info);
void gve_add_napi(struct gve_priv *priv, int ntfy_idx,
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format
2026-11-06 11:45 ` [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format Amaan Cheval
@ 2026-11-07 3:13 ` Joshua Washington
2026-11-09 9:38 ` Amaan Cheval
2026-11-10 12:04 ` netdev-bot+sashiko
1 sibling, 1 reply; 7+ messages in thread
From: Joshua Washington @ 2026-11-07 3:13 UTC (permalink / raw)
To: Amaan Cheval
Cc: netdev, hramamurthy, andrew+netdev, davem, edumazet, kuba,
pabeni, bcf, jordanrhee, przemyslaw.kitszel, maciej.fijalkowski,
pkaligineedi, maolson, csully, willemb, yangchun, npl,
awogbemila, shailend, nktgrg, maxyuan, bpf, john.fastabend, hawk,
sdf, daniel, ast, linux-kernel, stable
On Fri, Nov 6, 2026 at 3:46 AM Amaan Cheval <amaan.cheval@gmail.com> wrote:
>
> Commit d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ
> RDA") enabled XDP on DQO-RDA by dropping the queue_format check from
> verify_xdp_configuration(), which until then refused every format but
> GQI-QPL. Nothing replaced it for DQO-QPL: gve_set_netdev_xdp_features()
> advertises no XDP features there and gve_xdp_xmit() rejects it, but the
> core only checks that ndo_bpf exists, so a native XDP program, and an
> AF_XDP socket on top of it, can still be attached on DQO-QPL.
>
> The DQO-QPL RX path was never written for that. Its page accounting
> assumes the driver keeps a reference of its own across every handoff:
> gve_xdp_done_dqo() passes the buffer to xdp_do_redirect() and then
> recycles it with gve_reuse_buffer(), so a redirect target that releases
> the buffer synchronously, such as an AF_XDP socket in copy mode, can
> drop the page's last reference when pagecnt_bias runs out. The page is
> then freed while it is still DMA-mapped and registered in the QPL, and
> the driver posts it back to the device.
>
> Refuse XDP program setup on DQO-QPL in gve_verify_xdp_configuration(),
> matching the features the driver advertises. A zero-copy XSK pool bind
> is already refused by the core for the same reason, and a copy-mode
> bind never reaches the driver and is harmless without a program.
>
> Fixes: d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ RDA")
> Cc: stable@vger.kernel.org
> Signed-off-by: Amaan Cheval <amaan.cheval@gmail.com>
> ---
> drivers/net/ethernet/google/gve/gve_main.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
> index 2437cd8ba633..4e9e692a0ed0 100644
> --- a/drivers/net/ethernet/google/gve/gve_main.c
> +++ b/drivers/net/ethernet/google/gve/gve_main.c
> @@ -1723,6 +1723,12 @@ static int gve_verify_xdp_configuration(struct net_device *dev,
> struct gve_priv *priv = netdev_priv(dev);
> u16 max_xdp_mtu;
>
> + if (priv->queue_format == GVE_DQO_QPL_FORMAT) {
Thanks for implementing this!
Minor suggestion: Can we check based on dev->xdp_features
(NETDEV_XDP_ACT_BASIC) instead?
> + NL_SET_ERR_MSG_MOD(extack,
> + "XDP is not supported in DQO QPL queue format.");
> + return -EOPNOTSUPP;
> + }
> +
> if (dev->features & NETIF_F_GRO_HW) {
> NL_SET_ERR_MSG_MOD(extack,
> "XDP is not supported when HW-GRO is on.");
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format
2026-11-07 3:13 ` Joshua Washington
@ 2026-11-09 9:38 ` Amaan Cheval
0 siblings, 0 replies; 7+ messages in thread
From: Amaan Cheval @ 2026-11-09 9:38 UTC (permalink / raw)
To: Joshua Washington
Cc: netdev, hramamurthy, andrew+netdev, davem, edumazet, kuba,
pabeni, bcf, jordanrhee, przemyslaw.kitszel, maciej.fijalkowski,
pkaligineedi, maolson, csully, willemb, yangchun, npl,
awogbemila, shailend, nktgrg, maxyuan, bpf, john.fastabend, hawk,
sdf, daniel, ast, linux-kernel, stable
On Sat, Nov 7, 2026 at 8:43 AM Joshua Washington <joshwash@google.com> wrote:
>
> On Fri, Nov 6, 2026 at 3:46 AM Amaan Cheval <amaan.cheval@gmail.com> wrote:
> >
> > Commit d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ
> > RDA") enabled XDP on DQO-RDA by dropping the queue_format check from
> > verify_xdp_configuration(), which until then refused every format but
> > GQI-QPL. Nothing replaced it for DQO-QPL: gve_set_netdev_xdp_features()
> > advertises no XDP features there and gve_xdp_xmit() rejects it, but the
> > core only checks that ndo_bpf exists, so a native XDP program, and an
> > AF_XDP socket on top of it, can still be attached on DQO-QPL.
> >
> > The DQO-QPL RX path was never written for that. Its page accounting
> > assumes the driver keeps a reference of its own across every handoff:
> > gve_xdp_done_dqo() passes the buffer to xdp_do_redirect() and then
> > recycles it with gve_reuse_buffer(), so a redirect target that releases
> > the buffer synchronously, such as an AF_XDP socket in copy mode, can
> > drop the page's last reference when pagecnt_bias runs out. The page is
> > then freed while it is still DMA-mapped and registered in the QPL, and
> > the driver posts it back to the device.
> >
> > Refuse XDP program setup on DQO-QPL in gve_verify_xdp_configuration(),
> > matching the features the driver advertises. A zero-copy XSK pool bind
> > is already refused by the core for the same reason, and a copy-mode
> > bind never reaches the driver and is harmless without a program.
> >
> > Fixes: d8a8ca14c937 ("gve: add XDP_TX and XDP_REDIRECT support for DQ RDA")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Amaan Cheval <amaan.cheval@gmail.com>
> > ---
> > drivers/net/ethernet/google/gve/gve_main.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
> > index 2437cd8ba633..4e9e692a0ed0 100644
> > --- a/drivers/net/ethernet/google/gve/gve_main.c
> > +++ b/drivers/net/ethernet/google/gve/gve_main.c
> > @@ -1723,6 +1723,12 @@ static int gve_verify_xdp_configuration(struct net_device *dev,
> > struct gve_priv *priv = netdev_priv(dev);
> > u16 max_xdp_mtu;
> >
> > + if (priv->queue_format == GVE_DQO_QPL_FORMAT) {
>
> Thanks for implementing this!
>
> Minor suggestion: Can we check based on dev->xdp_features
> (NETDEV_XDP_ACT_BASIC) instead?
Thank you, yes, I'll respin.
>
> > + NL_SET_ERR_MSG_MOD(extack,
> > + "XDP is not supported in DQO QPL queue format.");
> > + return -EOPNOTSUPP;
> > + }
> > +
> > if (dev->features & NETIF_F_GRO_HW) {
> > NL_SET_ERR_MSG_MOD(extack,
> > "XDP is not supported when HW-GRO is on.");
> > --
> > 2.47.3
> >
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format
2026-11-06 11:45 ` [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format Amaan Cheval
2026-11-07 3:13 ` Joshua Washington
@ 2026-11-10 12:04 ` netdev-bot+sashiko
2026-11-10 13:33 ` Amaan Cheval
1 sibling, 1 reply; 7+ messages in thread
From: netdev-bot+sashiko @ 2026-11-10 12:04 UTC (permalink / raw)
To: amaan.cheval
Cc: netdev, joshwash, hramamurthy, andrew+netdev, davem, edumazet,
kuba, pabeni, bcf, jordanrhee, przemyslaw.kitszel,
maciej.fijalkowski, pkaligineedi, maolson, csully, willemb,
yangchun, npl, awogbemila, shailend, nktgrg, maxyuan, bpf,
john.fastabend, hawk, sdf, daniel, ast, linux-kernel, stable
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.
Critical: 0 · High: 1 · Medium: 0 · Low: 0
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [High] The patch is incomplete for GVE_GQI_RDA_FORMAT.
--
gve: block XDP on the DQO-QPL queue format
This patch adds a queue_format check to gve_verify_xdp_configuration()
that refuses XDP program setup on DQO-QPL. That check was lost when
d8a8ca14c937 enabled XDP on DQO-RDA. The DQO-QPL RX page accounting can
free a page that is still DMA-mapped when a redirect target releases the
buffer synchronously.
> diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
> index 2437cd8ba6331..4e9e692a0ed0a 100644
> --- a/drivers/net/ethernet/google/gve/gve_main.c
> +++ b/drivers/net/ethernet/google/gve/gve_main.c
> @@ -1723,6 +1723,12 @@ static int gve_verify_xdp_configuration(struct net_device *dev,
> struct gve_priv *priv = netdev_priv(dev);
> u16 max_xdp_mtu;
>
> + if (priv->queue_format == GVE_DQO_QPL_FORMAT) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "XDP is not supported in DQO QPL queue format.");
> + return -EOPNOTSUPP;
> + }
> +
[Severity: High]
Does this leave GVE_GQI_RDA_FORMAT uncovered? The commit message says the
check removed by d8a8ca14c937 "refused every format but GQI-QPL", so it
blocked GQI-RDA as well as DQO-QPL. Only DQO-QPL is added back here.
GQI-RDA also falls into the else branch of gve_set_netdev_xdp_features():
} else {
xdp_features = 0;
}
and gve_xdp_xmit() rejects it too:
if (priv->queue_format == GVE_GQI_QPL_FORMAT)
return gve_xdp_xmit_gqi(dev, n, frames, flags);
else if (priv->queue_format == GVE_DQO_RDA_FORMAT)
return gve_xdp_xmit_dqo(dev, n, frames, flags);
return -EOPNOTSUPP;
On GQI-RDA, though, every remaining check in this function can pass:
- GQI has no NETIF_F_GRO_HW.
- Header split is DQO-RDA only.
- packet_buffer_size defaults to 2K.
- GVE_RX_PAD is only subtracted for GQI-QPL.
- The rx/tx queue count condition can be met with ethtool -L.
Once verification passes on a running interface, the path is:
gve_xdp()->gve_set_xdp()->gve_configure_rings_xdp()->gve_adjust_config()
->gve_queues_start()->gve_reg_xdp_info()
On GQI-RDA, gve_is_qpl() is false, so gve_reg_xdp_info() takes this
branch:
else
err = xdp_rxq_info_reg_mem_model(&rx->xdp_rxq,
MEM_TYPE_PAGE_POOL,
rx->dqo.page_pool);
On a GQI ring, rx->dqo.page_pool is NULL because gve_rx_alloc_ring_gqi()
memsets the ring. __xdp_reg_mem_model() therefore returns -EINVAL. By
then gve_adjust_config() has already closed the old queues, so it logs
"!!! DISABLING ALL QUEUES !!!" and turns the device down.
Before that failure, gve_queues_start() has already set:
priv->tx_cfg.num_xdp_queues = tx_alloc_cfg->num_xdp_rings;
and nothing rolls it back. A later ifdown/ifup goes through
gve_open()->gve_get_curr_alloc_cfgs(), rebuilds the XDP rings, and fails
in gve_reg_xdp_info() again. Does the NIC then stay down until a device
reset? If the interface is already down at attach time, gve_set_xdp()
installs the program, and every later gve_open() fails with -EINVAL.
There is also a NULL dereference that only this failure hides.
gve_tx_fill_xdp() uses tx->tx_fifo.base and
tx->tx_fifo.qpl->page_buses. On raw-addressing GQI TX rings these are
never set up: gve_tx_alloc_ring_gqi() skips the FIFO/QPL setup, and
gve_can_tx() skips the FIFO check. That dereference would become
reachable if GQI-RDA mem model registration ever succeeded.
Would an allowlist (accept only GQI_QPL and DQO_RDA) be a closer match to
"matching the features the driver advertises"? Checking for
NETDEV_XDP_ACT_BASIC in dev->xdp_features would also work.
With the Fixes: d8a8ca14c937 and Cc: stable tags, backporters may assume
that regression is fully closed. The later patch in the series ("gve: fix
RX page refcount overflow from the pagecnt bias") does not touch
gve_verify_xdp_configuration().
> if (dev->features & NETIF_F_GRO_HW) {
> NL_SET_ERR_MSG_MOD(extack,
> "XDP is not supported when HW-GRO is on.");
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261106114551.212675-1-amaan.cheval%40gmail.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format
2026-11-10 12:04 ` netdev-bot+sashiko
@ 2026-11-10 13:33 ` Amaan Cheval
0 siblings, 0 replies; 7+ messages in thread
From: Amaan Cheval @ 2026-11-10 13:33 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: netdev, joshwash, hramamurthy, andrew+netdev, davem, edumazet,
kuba, pabeni, bcf, jordanrhee, przemyslaw.kitszel,
maciej.fijalkowski, pkaligineedi, maolson, csully, willemb,
yangchun, npl, awogbemila, shailend, nktgrg, maxyuan, bpf,
john.fastabend, hawk, sdf, daniel, ast, linux-kernel, stable
On Tue, Nov 10, 2026 at 5:35 PM <netdev-bot+sashiko@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 1 · Medium: 0 · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] The patch is incomplete for GVE_GQI_RDA_FORMAT.
>
> --
>
> gve: block XDP on the DQO-QPL queue format
>
> This patch adds a queue_format check to gve_verify_xdp_configuration()
> that refuses XDP program setup on DQO-QPL. That check was lost when
> d8a8ca14c937 enabled XDP on DQO-RDA. The DQO-QPL RX page accounting can
> free a page that is still DMA-mapped when a redirect target releases the
> buffer synchronously.
>
> > diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
> > index 2437cd8ba6331..4e9e692a0ed0a 100644
> > --- a/drivers/net/ethernet/google/gve/gve_main.c
> > +++ b/drivers/net/ethernet/google/gve/gve_main.c
> > @@ -1723,6 +1723,12 @@ static int gve_verify_xdp_configuration(struct net_device *dev,
> > struct gve_priv *priv = netdev_priv(dev);
> > u16 max_xdp_mtu;
> >
> > + if (priv->queue_format == GVE_DQO_QPL_FORMAT) {
> > + NL_SET_ERR_MSG_MOD(extack,
> > + "XDP is not supported in DQO QPL queue format.");
> > + return -EOPNOTSUPP;
> > + }
> > +
>
> [Severity: High]
> Does this leave GVE_GQI_RDA_FORMAT uncovered? The commit message says the
> check removed by d8a8ca14c937 "refused every format but GQI-QPL", so it
> blocked GQI-RDA as well as DQO-QPL. Only DQO-QPL is added back here.
pw-bot: cr
v5 addresses this here:
https://patchwork.kernel.org/series/1205920/
>
> GQI-RDA also falls into the else branch of gve_set_netdev_xdp_features():
>
> } else {
> xdp_features = 0;
> }
>
> and gve_xdp_xmit() rejects it too:
>
> if (priv->queue_format == GVE_GQI_QPL_FORMAT)
> return gve_xdp_xmit_gqi(dev, n, frames, flags);
> else if (priv->queue_format == GVE_DQO_RDA_FORMAT)
> return gve_xdp_xmit_dqo(dev, n, frames, flags);
>
> return -EOPNOTSUPP;
>
> On GQI-RDA, though, every remaining check in this function can pass:
>
> - GQI has no NETIF_F_GRO_HW.
> - Header split is DQO-RDA only.
> - packet_buffer_size defaults to 2K.
> - GVE_RX_PAD is only subtracted for GQI-QPL.
> - The rx/tx queue count condition can be met with ethtool -L.
>
> Once verification passes on a running interface, the path is:
>
> gve_xdp()->gve_set_xdp()->gve_configure_rings_xdp()->gve_adjust_config()
> ->gve_queues_start()->gve_reg_xdp_info()
>
> On GQI-RDA, gve_is_qpl() is false, so gve_reg_xdp_info() takes this
> branch:
>
> else
> err = xdp_rxq_info_reg_mem_model(&rx->xdp_rxq,
> MEM_TYPE_PAGE_POOL,
> rx->dqo.page_pool);
>
> On a GQI ring, rx->dqo.page_pool is NULL because gve_rx_alloc_ring_gqi()
> memsets the ring. __xdp_reg_mem_model() therefore returns -EINVAL. By
> then gve_adjust_config() has already closed the old queues, so it logs
> "!!! DISABLING ALL QUEUES !!!" and turns the device down.
>
> Before that failure, gve_queues_start() has already set:
>
> priv->tx_cfg.num_xdp_queues = tx_alloc_cfg->num_xdp_rings;
>
> and nothing rolls it back. A later ifdown/ifup goes through
> gve_open()->gve_get_curr_alloc_cfgs(), rebuilds the XDP rings, and fails
> in gve_reg_xdp_info() again. Does the NIC then stay down until a device
> reset? If the interface is already down at attach time, gve_set_xdp()
> installs the program, and every later gve_open() fails with -EINVAL.
>
> There is also a NULL dereference that only this failure hides.
> gve_tx_fill_xdp() uses tx->tx_fifo.base and
> tx->tx_fifo.qpl->page_buses. On raw-addressing GQI TX rings these are
> never set up: gve_tx_alloc_ring_gqi() skips the FIFO/QPL setup, and
> gve_can_tx() skips the FIFO check. That dereference would become
> reachable if GQI-RDA mem model registration ever succeeded.
>
> Would an allowlist (accept only GQI_QPL and DQO_RDA) be a closer match to
> "matching the features the driver advertises"? Checking for
> NETDEV_XDP_ACT_BASIC in dev->xdp_features would also work.
>
> With the Fixes: d8a8ca14c937 and Cc: stable tags, backporters may assume
> that regression is fully closed. The later patch in the series ("gve: fix
> RX page refcount overflow from the pagecnt bias") does not touch
> gve_verify_xdp_configuration().
>
> > if (dev->features & NETIF_F_GRO_HW) {
> > NL_SET_ERR_MSG_MOD(extack,
> > "XDP is not supported when HW-GRO is on.");
>
> [ ... ]
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261106114551.212675-1-amaan.cheval%40gmail.com
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-11-10 13:33 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06 11:45 [PATCH net v4 0/2] gve: fix RX page refcount overflow with the pagecnt bias Amaan Cheval
2026-11-06 11:45 ` [PATCH net v4 1/2] gve: block XDP on the DQO-QPL queue format Amaan Cheval
2026-11-07 3:13 ` Joshua Washington
2026-11-09 9:38 ` Amaan Cheval
2026-11-10 12:04 ` netdev-bot+sashiko
2026-11-10 13:33 ` Amaan Cheval
2026-11-06 11:45 ` [PATCH net v4 2/2] gve: fix RX page refcount overflow from the pagecnt bias Amaan Cheval
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®