RE: [PATCH net] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets
From: Jagielski, Jedrzej <hidden>
Date: 2026-07-10 09:44:17
Also in:
lkml
From: Harshaka Narayana <redacted> 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 <redacted>
Signed-off-by: Ronak Doshi <ronak.doshi@broadcom.com>
Signed-off-by: Sankararaman Jayaraman <redacted>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
quoted hunk ↗ jump to hunk
--- 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
quoted hunk ↗ jump to hunk
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