RE: [PATCH net] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets

From: Jagielski, Jedrzej

Date: Fri Jul 10 2026 - 05:47:50 EST


From: Harshaka Narayana <harshaka.narayana@xxxxxxxxxxxx>
Sent: Thursday, July 9, 2026 8:12 PM

>vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the
>outer header, but for a Geneve-encapsulated packet the device can set
>them based on the inner header instead, signalled by the
>VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the
>function never skips the outer encapsulation, this mismatch triggers:
>
>- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer
> protocol is UDP (Geneve), not TCP.
>- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner
> IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa).
>
>Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the
>function cannot locate the inner header it would need to parse. Also
>convert the remaining BUG_ON()s in this function to return 0
>defensively.
>
>Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)")
>Signed-off-by: Harshaka Narayana <harshaka.narayana@xxxxxxxxxxxx>
>Signed-off-by: Ronak Doshi <ronak.doshi@xxxxxxxxxxxx>
>Signed-off-by: Sankararaman Jayaraman <sankararaman.jayaraman@xxxxxxxxxxxx>

Hi Harshaka

you signed-off-by tag should be the last one as you're the sender
also unclear what was the roles of other people mentioned here - if
they are co-developers please add appropriate tags

>---
> drivers/net/vmxnet3/vmxnet3_drv.c | 24 ++++++++++++++++++------
> 1 file changed, 18 insertions(+), 6 deletions(-)
>
>diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
>index 40522afc0532..dedf4082eb6c 100644
>--- a/drivers/net/vmxnet3/vmxnet3_drv.c
>+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
>@@ -1530,7 +1530,13 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
> struct ipv6hdr *ipv6;
> struct tcphdr *tcp;
> } hdr;
>- BUG_ON(gdesc->rcd.tcp == 0);
>+
>+ /* v4/v6/tcp then describe the inner header, which we can't locate. */
>+ if (le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))
>+ return 0;
>+
>+ if (gdesc->rcd.tcp == 0)
>+ return 0;

nit: as both above return 0 they can be combined i believe

>
> maplen = skb_headlen(skb);
> if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen))
>@@ -1544,15 +1550,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
>
> hdr.eth = eth_hdr(skb);
> if (gdesc->rcd.v4) {
>- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) &&
>- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP));
>+ if (hdr.eth->h_proto != htons(ETH_P_IP) &&
>+ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP))
>+ return 0;
>+
> hdr.ptr += hlen;
>- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP);
>+ if (hdr.ipv4->protocol != IPPROTO_TCP)
>+ return 0;
>+
> hlen = hdr.ipv4->ihl << 2;
> hdr.ptr += hdr.ipv4->ihl << 2;
> } else if (gdesc->rcd.v6) {
>- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) &&
>- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6));
>+ if (hdr.eth->h_proto != htons(ETH_P_IPV6) &&
>+ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6))
>+ return 0;
>+
> hdr.ptr += hlen;
> /* Use an estimated value, since we also need to handle
> * TSO case.
>--
>2.52.0