Netdev List
 help / color / mirror / Atom feed
* [PATCH net 0/2] net: fix skb->protocol not updated after VLAN network header adjustment
@ 2026-08-05 10:53 wei.fang
  2026-08-05 10:53 ` [PATCH net 1/2] net: packet: " wei.fang
  2026-08-05 10:53 ` [PATCH net 2/2] net: tap: " wei.fang
  0 siblings, 2 replies; 8+ messages in thread
From: wei.fang @ 2026-08-05 10:53 UTC (permalink / raw)
  To: willemdebruijn.kernel, davem, edumazet, kuba, pabeni, horms,
	liuhangbin, mst, jasowangio, andrew+netdev, ast, daniel, hawk,
	john.fastabend, sdf
  Cc: wei.fang, imx, netdev, linux-kernel, bpf

From: Wei Fang <wei.fang@nxp.com>

After calling skb_set_network_header() to skip past the VLAN tag,
skb->protocol still points to the outer VLAN EtherType. If
skb_probe_transport_header() is then called without updating
skb->protocol to the inner protocol, the flow dissector will misparse
the inner header as a VLAN header and fail to set transport_header,
leaving it at its uninitialized sentinel value (~0U).

This series fixes two instances of this bug in packet_parse_headers()
and tap_get_user_xdp() by assigning the return value of
vlan_get_protocol_and_depth() to skb->protocol after
skb_set_network_header().

Wei Fang (2):
  net: packet: fix skb->protocol not updated after VLAN network header
    adjustment
  net: tap: fix skb->protocol not updated after VLAN network header
    adjustment

 drivers/net/tap.c      | 12 +++++++++---
 net/packet/af_packet.c | 12 +++++++++---
 2 files changed, 18 insertions(+), 6 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH net 1/2] net: packet: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-05 10:53 [PATCH net 0/2] net: fix skb->protocol not updated after VLAN network header adjustment wei.fang
@ 2026-08-05 10:53 ` wei.fang
  2026-08-05 10:53 ` [PATCH net 2/2] net: tap: " wei.fang
  1 sibling, 0 replies; 8+ messages in thread
From: wei.fang @ 2026-08-05 10:53 UTC (permalink / raw)
  To: willemdebruijn.kernel, davem, edumazet, kuba, pabeni, horms,
	liuhangbin, mst, jasowangio, andrew+netdev, ast, daniel, hawk,
	john.fastabend, sdf
  Cc: wei.fang, imx, netdev, linux-kernel, bpf

From: Wei Fang <wei.fang@nxp.com>

In packet_parse_headers(), when processing a VLAN-tagged frame on a
SOCK_RAW AF_PACKET socket, skb_set_network_header() is called with the
depth returned by vlan_get_protocol_and_depth() to advance network_header
past the VLAN tag to the inner protocol header. However, skb->protocol
was not updated to reflect the inner EtherType resolved by
vlan_get_protocol_and_depth(), leaving it pointing to the outer VLAN
EtherType (e.g. ETH_P_8021Q).

This mismatch causes skb_probe_transport_header() to invoke the flow
dissector with proto=ETH_P_8021Q but nhoff already pointing past the
VLAN tag to the inner header. The dissector interprets the inner header
bytes as a VLAN header, fails to find a recognizable encapsulated
protocol, and returns false. Consequently, transport_header is never
set and remains at its uninitialized sentinel value (~0U = 0xFFFF).

Any subsequent code that calls skb_transport_header() or udp_hdr() on
such an skb will dereference a pointer 65535 bytes past skb->head,
potentially corrupting arbitrary kernel memory.

Save the return value of vlan_get_protocol_and_depth(), which already
resolves the inner EtherType, and assign it to skb->protocol after
skb_set_network_header(). This keeps skb->protocol and network_header
consistent when skb_probe_transport_header() is called, allowing the
flow dissector to correctly identify the transport layer header.

Fixes: dfed913e8b55 ("net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO")
Assisted-by: WChat:claude-opus-4-8
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 net/packet/af_packet.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 0e1355be89f6..a62d445047c0 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1945,9 +1945,15 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
 
 	/* Move network header to the right position for VLAN tagged packets */
 	if (likely(skb->dev->type == ARPHRD_ETHER) &&
-	    eth_type_vlan(skb->protocol) &&
-	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
-		skb_set_network_header(skb, depth);
+	    eth_type_vlan(skb->protocol)) {
+		__be16 proto = vlan_get_protocol_and_depth(skb, skb->protocol,
+							   &depth);
+
+		if (proto != 0) {
+			skb_set_network_header(skb, depth);
+			skb->protocol = proto;
+		}
+	}
 
 	skb_probe_transport_header(skb);
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net 2/2] net: tap: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-05 10:53 [PATCH net 0/2] net: fix skb->protocol not updated after VLAN network header adjustment wei.fang
  2026-08-05 10:53 ` [PATCH net 1/2] net: packet: " wei.fang
@ 2026-08-05 10:53 ` wei.fang
  2026-08-05 12:48   ` Willem de Bruijn
  1 sibling, 1 reply; 8+ messages in thread
From: wei.fang @ 2026-08-05 10:53 UTC (permalink / raw)
  To: willemdebruijn.kernel, davem, edumazet, kuba, pabeni, horms,
	liuhangbin, mst, jasowangio, andrew+netdev, ast, daniel, hawk,
	john.fastabend, sdf
  Cc: wei.fang, imx, netdev, linux-kernel, bpf

From: Wei Fang <wei.fang@nxp.com>

In tap_get_user_xdp(), when processing a VLAN-tagged frame,
skb_set_network_header() is called with the depth returned by
vlan_get_protocol_and_depth() to advance network_header past the VLAN
tag to the inner protocol header. However, skb->protocol was not updated
to reflect the inner EtherType, leaving it pointing to the outer VLAN
EtherType (e.g. ETH_P_8021Q).

This mismatch has two consequences. First, skb_probe_transport_header()
is called after the VLAN adjustment with proto=ETH_P_8021Q but nhoff
already pointing past the VLAN tag to the inner header. The flow
dissector interprets the inner header bytes as a VLAN header, fails to
find a recognizable encapsulated protocol, and returns false.
Consequently, transport_header is never set and remains at its
uninitialized sentinel value (~0U), causing any subsequent
skb_transport_header() or udp_hdr() call to dereference a pointer
65535 bytes past skb->head, potentially corrupting arbitrary kernel
memory. Second, TC egress and eBPF programs that inspect skb->protocol
directly (e.g. bpf_skb_net_base_len(), bpf_skb_net_grow(),
__bpf_redirect_neigh()) will see ETH_P_8021Q instead of the inner
protocol and behave incorrectly.

Save the return value of vlan_get_protocol_and_depth(), which already
resolves the inner EtherType, and assign it to skb->protocol after
skb_set_network_header(). This keeps skb->protocol and network_header
consistent for all subsequent processing.

Fixes: 8c76e77f9069 ("tap: call skb_probe_transport_header after setting skb->dev")
Assisted-by: WChat:claude-opus-4-8
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/net/tap.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index fae115915c8e..afcc4919bd04 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -1081,9 +1081,15 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
 	}
 
 	/* Move network header to the right position for VLAN tagged packets */
-	if (eth_type_vlan(skb->protocol) &&
-	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
-		skb_set_network_header(skb, depth);
+	if (eth_type_vlan(skb->protocol)) {
+		__be16 proto = vlan_get_protocol_and_depth(skb, skb->protocol,
+							   &depth);
+
+		if (proto != 0) {
+			skb_set_network_header(skb, depth);
+			skb->protocol = proto;
+		}
+	}
 
 	rcu_read_lock();
 	tap = rcu_dereference(q->tap);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH net 2/2] net: tap: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-05 10:53 ` [PATCH net 2/2] net: tap: " wei.fang
@ 2026-08-05 12:48   ` Willem de Bruijn
  2026-08-06  2:10     ` Wei Fang
  0 siblings, 1 reply; 8+ messages in thread
From: Willem de Bruijn @ 2026-08-05 12:48 UTC (permalink / raw)
  To: wei.fang, willemdebruijn.kernel, davem, edumazet, kuba, pabeni,
	horms, liuhangbin, mst, jasowangio, andrew+netdev, ast, daniel,
	hawk, john.fastabend, sdf
  Cc: wei.fang, imx, netdev, linux-kernel, bpf

wei.fang@ wrote:
> From: Wei Fang <wei.fang@nxp.com>
> 
> In tap_get_user_xdp(), when processing a VLAN-tagged frame,
> skb_set_network_header() is called with the depth returned by
> vlan_get_protocol_and_depth() to advance network_header past the VLAN
> tag to the inner protocol header. However, skb->protocol was not updated
> to reflect the inner EtherType, leaving it pointing to the outer VLAN
> EtherType (e.g. ETH_P_8021Q).
> 
> This mismatch has two consequences. First, skb_probe_transport_header()
> is called after the VLAN adjustment with proto=ETH_P_8021Q but nhoff
> already pointing past the VLAN tag to the inner header. The flow
> dissector interprets the inner header bytes as a VLAN header, fails to
> find a recognizable encapsulated protocol, and returns false.
> Consequently, transport_header is never set and remains at its
> uninitialized sentinel value (~0U), causing any subsequent
> skb_transport_header() or udp_hdr() call to dereference a pointer
> 65535 bytes past skb->head, potentially corrupting arbitrary kernel
> memory. Second, TC egress and eBPF programs that inspect skb->protocol
> directly (e.g. bpf_skb_net_base_len(), bpf_skb_net_grow(),
> __bpf_redirect_neigh()) will see ETH_P_8021Q instead of the inner
> protocol and behave incorrectly.
> 
> Save the return value of vlan_get_protocol_and_depth(), which already
> resolves the inner EtherType, and assign it to skb->protocol after
> skb_set_network_header(). This keeps skb->protocol and network_header
> consistent for all subsequent processing.
> 
> Fixes: 8c76e77f9069 ("tap: call skb_probe_transport_header after setting skb->dev")
> Assisted-by: WChat:claude-opus-4-8
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> ---
>  drivers/net/tap.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/tap.c b/drivers/net/tap.c
> index fae115915c8e..afcc4919bd04 100644
> --- a/drivers/net/tap.c
> +++ b/drivers/net/tap.c
> @@ -1081,9 +1081,15 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
>  	}
>  
>  	/* Move network header to the right position for VLAN tagged packets */
> -	if (eth_type_vlan(skb->protocol) &&
> -	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
> -		skb_set_network_header(skb, depth);
> +	if (eth_type_vlan(skb->protocol)) {
> +		__be16 proto = vlan_get_protocol_and_depth(skb, skb->protocol,
> +							   &depth);
> +
> +		if (proto != 0) {
> +			skb_set_network_header(skb, depth);
> +			skb->protocol = proto;
> +		}
> +	}

Does the same apply to the same call in tap_get_user?

And in general to other callers of vlan_get_protocol_and_depth,
including through wrapper skb_network_protocol?

>  
>  	rcu_read_lock();
>  	tap = rcu_dereference(q->tap);
> -- 
> 2.34.1
> 



^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH net 2/2] net: tap: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-05 12:48   ` Willem de Bruijn
@ 2026-08-06  2:10     ` Wei Fang
  2026-08-06 10:06       ` Wei Fang
  0 siblings, 1 reply; 8+ messages in thread
From: Wei Fang @ 2026-08-06  2:10 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: imx@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Wei Fang (OSS),
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, liuhangbin@gmail.com,
	mst@redhat.com, jasowangio@gmail.com, andrew+netdev@lunn.ch,
	ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org,
	john.fastabend@gmail.com, sdf@fomichev.me

> > In tap_get_user_xdp(), when processing a VLAN-tagged frame,
> > skb_set_network_header() is called with the depth returned by
> > vlan_get_protocol_and_depth() to advance network_header past the VLAN
> > tag to the inner protocol header. However, skb->protocol was not updated
> > to reflect the inner EtherType, leaving it pointing to the outer VLAN
> > EtherType (e.g. ETH_P_8021Q).
> >
> > This mismatch has two consequences. First, skb_probe_transport_header()
> > is called after the VLAN adjustment with proto=ETH_P_8021Q but nhoff
> > already pointing past the VLAN tag to the inner header. The flow
> > dissector interprets the inner header bytes as a VLAN header, fails to
> > find a recognizable encapsulated protocol, and returns false.
> > Consequently, transport_header is never set and remains at its
> > uninitialized sentinel value (~0U), causing any subsequent
> > skb_transport_header() or udp_hdr() call to dereference a pointer
> > 65535 bytes past skb->head, potentially corrupting arbitrary kernel
> > memory. Second, TC egress and eBPF programs that inspect skb->protocol
> > directly (e.g. bpf_skb_net_base_len(), bpf_skb_net_grow(),
> > __bpf_redirect_neigh()) will see ETH_P_8021Q instead of the inner
> > protocol and behave incorrectly.
> >
> > Save the return value of vlan_get_protocol_and_depth(), which already
> > resolves the inner EtherType, and assign it to skb->protocol after
> > skb_set_network_header(). This keeps skb->protocol and network_header
> > consistent for all subsequent processing.
> >
> > Fixes: 8c76e77f9069 ("tap: call skb_probe_transport_header after setting
> skb->dev")
> > Assisted-by: WChat:claude-opus-4-8
> > Signed-off-by: Wei Fang <wei.fang@nxp.com>
> > ---
> >  drivers/net/tap.c | 12 +++++++++---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/tap.c b/drivers/net/tap.c
> > index fae115915c8e..afcc4919bd04 100644
> > --- a/drivers/net/tap.c
> > +++ b/drivers/net/tap.c
> > @@ -1081,9 +1081,15 @@ static int tap_get_user_xdp(struct tap_queue *q,
> struct xdp_buff *xdp)
> >  	}
> >
> >  	/* Move network header to the right position for VLAN tagged packets */
> > -	if (eth_type_vlan(skb->protocol) &&
> > -	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
> > -		skb_set_network_header(skb, depth);
> > +	if (eth_type_vlan(skb->protocol)) {
> > +		__be16 proto = vlan_get_protocol_and_depth(skb, skb->protocol,
> > +							   &depth);
> > +
> > +		if (proto != 0) {
> > +			skb_set_network_header(skb, depth);
> > +			skb->protocol = proto;
> > +		}
> > +	}
> 
> Does the same apply to the same call in tap_get_user?

The situation of tap_get_user() is different, skb_probe_transport_header()
is called before the VLAN adjustment block. So I think transport_header
should be correct. The only concern is whether skb->protocol needs to be
updated after calling skb_set_network_header().

I'm not sure as I am not fairly familiar with the tap driver. I added this patch
because Sashiko reported that the tap driver has the same issue as af_packet.

> 
> And in general to other callers of vlan_get_protocol_and_depth,
> including through wrapper skb_network_protocol?

I don't think this issue exists elsewhere. The issue arises because
skb_probe_transport_header() is called after skb_set_network_header(), and
at this point, skb->protocol and network_header are not synchronized ( In
__skb_flow_dissect(), nhoff = skb_network_offset(skb) but proto is
ETH_P_8021Q or ETH_P_8021AD)), causing skb_probe_transport_header() to
fail to set transport_header correctly.

Perhaps the correct approach would be to restore the original `skb->protocol`
value after `skb_probe_transport_header()`, maintaining consistency with the
previous behavior; otherwise, it might introduce new issues.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH net 2/2] net: tap: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-06  2:10     ` Wei Fang
@ 2026-08-06 10:06       ` Wei Fang
  2026-08-06 14:12         ` Willem de Bruijn
  0 siblings, 1 reply; 8+ messages in thread
From: Wei Fang @ 2026-08-06 10:06 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: imx@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Wei Fang (OSS),
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, liuhangbin@gmail.com,
	mst@redhat.com, jasowangio@gmail.com, andrew+netdev@lunn.ch,
	ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org,
	john.fastabend@gmail.com, sdf@fomichev.me

> > > --- a/drivers/net/tap.c
> > > +++ b/drivers/net/tap.c
> > > @@ -1081,9 +1081,15 @@ static int tap_get_user_xdp(struct tap_queue
> *q,
> > struct xdp_buff *xdp)
> > >  	}
> > >
> > >  	/* Move network header to the right position for VLAN tagged
> packets */
> > > -	if (eth_type_vlan(skb->protocol) &&
> > > -	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
> > > -		skb_set_network_header(skb, depth);
> > > +	if (eth_type_vlan(skb->protocol)) {
> > > +		__be16 proto = vlan_get_protocol_and_depth(skb,
> skb->protocol,
> > > +							   &depth);
> > > +
> > > +		if (proto != 0) {
> > > +			skb_set_network_header(skb, depth);
> > > +			skb->protocol = proto;
> > > +		}
> > > +	}
> >
> > Does the same apply to the same call in tap_get_user?
> 
> The situation of tap_get_user() is different, skb_probe_transport_header()
> is called before the VLAN adjustment block. So I think transport_header
> should be correct. The only concern is whether skb->protocol needs to be
> updated after calling skb_set_network_header().
> 
> I'm not sure as I am not fairly familiar with the tap driver. I added this patch
> because Sashiko reported that the tap driver has the same issue as af_packet.
> 
> >
> > And in general to other callers of vlan_get_protocol_and_depth,
> > including through wrapper skb_network_protocol?
> 
> I don't think this issue exists elsewhere. The issue arises because
> skb_probe_transport_header() is called after skb_set_network_header(), and
> at this point, skb->protocol and network_header are not synchronized ( In
> __skb_flow_dissect(), nhoff = skb_network_offset(skb) but proto is
> ETH_P_8021Q or ETH_P_8021AD)), causing skb_probe_transport_header() to
> fail to set transport_header correctly.
> 
> Perhaps the correct approach would be to restore the original `skb->protocol`
> value after `skb_probe_transport_header()`, maintaining consistency with the
> previous behavior; otherwise, it might introduce new issues.

For AF_PACKET, it has been confirmed that skb->protocol does not need to be
restored to its initial value; otherwise, the egress tc flower for protocol ip will
not match the packet. A known issue is that the packets cannot match the egress
TC flower rules for protocol 802.1Q, but this issue exists before this series. This
is likely a limitation of using AF_PACKET to send packets.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH net 2/2] net: tap: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-06 10:06       ` Wei Fang
@ 2026-08-06 14:12         ` Willem de Bruijn
  2026-08-07  2:21           ` Wei Fang
  0 siblings, 1 reply; 8+ messages in thread
From: Willem de Bruijn @ 2026-08-06 14:12 UTC (permalink / raw)
  To: Wei Fang, Willem de Bruijn
  Cc: imx@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Wei Fang (OSS),
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, liuhangbin@gmail.com,
	mst@redhat.com, jasowangio@gmail.com, andrew+netdev@lunn.ch,
	ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org,
	john.fastabend@gmail.com, sdf@fomichev.me

Wei Fang wrote:
> > > > --- a/drivers/net/tap.c
> > > > +++ b/drivers/net/tap.c
> > > > @@ -1081,9 +1081,15 @@ static int tap_get_user_xdp(struct tap_queue
> > *q,
> > > struct xdp_buff *xdp)
> > > >  	}
> > > >
> > > >  	/* Move network header to the right position for VLAN tagged
> > packets */
> > > > -	if (eth_type_vlan(skb->protocol) &&
> > > > -	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
> > > > -		skb_set_network_header(skb, depth);
> > > > +	if (eth_type_vlan(skb->protocol)) {
> > > > +		__be16 proto = vlan_get_protocol_and_depth(skb,
> > skb->protocol,
> > > > +							   &depth);
> > > > +
> > > > +		if (proto != 0) {
> > > > +			skb_set_network_header(skb, depth);
> > > > +			skb->protocol = proto;
> > > > +		}
> > > > +	}
> > >
> > > Does the same apply to the same call in tap_get_user?
> > 
> > The situation of tap_get_user() is different, skb_probe_transport_header()
> > is called before the VLAN adjustment block. So I think transport_header
> > should be correct. The only concern is whether skb->protocol needs to be
> > updated after calling skb_set_network_header().
> > 
> > I'm not sure as I am not fairly familiar with the tap driver. I added this patch
> > because Sashiko reported that the tap driver has the same issue as af_packet.
> > 
> > >
> > > And in general to other callers of vlan_get_protocol_and_depth,
> > > including through wrapper skb_network_protocol?
> > 
> > I don't think this issue exists elsewhere. The issue arises because
> > skb_probe_transport_header() is called after skb_set_network_header(), and
> > at this point, skb->protocol and network_header are not synchronized ( In
> > __skb_flow_dissect(), nhoff = skb_network_offset(skb) but proto is
> > ETH_P_8021Q or ETH_P_8021AD)), causing skb_probe_transport_header() to
> > fail to set transport_header correctly.
> > 
> > Perhaps the correct approach would be to restore the original `skb->protocol`
> > value after `skb_probe_transport_header()`, maintaining consistency with the
> > previous behavior; otherwise, it might introduce new issues.
> 
> For AF_PACKET, it has been confirmed that skb->protocol does not need to be
> restored to its initial value; otherwise, the egress tc flower for protocol ip will
> not match the packet. A known issue is that the packets cannot match the egress
> TC flower rules for protocol 802.1Q, but this issue exists before this series. This
> is likely a limitation of using AF_PACKET to send packets.

Actually this update of network header to start of the IP header may
have been a mistake. If userspace inserts a VLAN packet, that is what
should enter the stack.

But for this specific issue: would it make sense to just move
skb_probe_transport_header before that adjustment?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH net 2/2] net: tap: fix skb->protocol not updated after VLAN network header adjustment
  2026-08-06 14:12         ` Willem de Bruijn
@ 2026-08-07  2:21           ` Wei Fang
  0 siblings, 0 replies; 8+ messages in thread
From: Wei Fang @ 2026-08-07  2:21 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: imx@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Wei Fang (OSS),
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, liuhangbin@gmail.com,
	mst@redhat.com, jasowangio@gmail.com, andrew+netdev@lunn.ch,
	ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org,
	john.fastabend@gmail.com, sdf@fomichev.me

> > > > > --- a/drivers/net/tap.c
> > > > > +++ b/drivers/net/tap.c
> > > > > @@ -1081,9 +1081,15 @@ static int tap_get_user_xdp(struct
> tap_queue
> > > *q,
> > > > struct xdp_buff *xdp)
> > > > >  	}
> > > > >
> > > > >  	/* Move network header to the right position for VLAN tagged
> > > packets */
> > > > > -	if (eth_type_vlan(skb->protocol) &&
> > > > > -	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
> > > > > -		skb_set_network_header(skb, depth);
> > > > > +	if (eth_type_vlan(skb->protocol)) {
> > > > > +		__be16 proto = vlan_get_protocol_and_depth(skb,
> > > skb->protocol,
> > > > > +							   &depth);
> > > > > +
> > > > > +		if (proto != 0) {
> > > > > +			skb_set_network_header(skb, depth);
> > > > > +			skb->protocol = proto;
> > > > > +		}
> > > > > +	}
> > > >
> > > > Does the same apply to the same call in tap_get_user?
> > >
> > > The situation of tap_get_user() is different, skb_probe_transport_header()
> > > is called before the VLAN adjustment block. So I think transport_header
> > > should be correct. The only concern is whether skb->protocol needs to be
> > > updated after calling skb_set_network_header().
> > >
> > > I'm not sure as I am not fairly familiar with the tap driver. I added this patch
> > > because Sashiko reported that the tap driver has the same issue as
> af_packet.
> > >
> > > >
> > > > And in general to other callers of vlan_get_protocol_and_depth,
> > > > including through wrapper skb_network_protocol?
> > >
> > > I don't think this issue exists elsewhere. The issue arises because
> > > skb_probe_transport_header() is called after skb_set_network_header(),
> and
> > > at this point, skb->protocol and network_header are not synchronized ( In
> > > __skb_flow_dissect(), nhoff = skb_network_offset(skb) but proto is
> > > ETH_P_8021Q or ETH_P_8021AD)), causing skb_probe_transport_header()
> to
> > > fail to set transport_header correctly.
> > >
> > > Perhaps the correct approach would be to restore the original
> `skb->protocol`
> > > value after `skb_probe_transport_header()`, maintaining consistency with
> the
> > > previous behavior; otherwise, it might introduce new issues.
> >
> > For AF_PACKET, it has been confirmed that skb->protocol does not need to be
> > restored to its initial value; otherwise, the egress tc flower for protocol ip will
> > not match the packet. A known issue is that the packets cannot match the
> egress
> > TC flower rules for protocol 802.1Q, but this issue exists before this series. This
> > is likely a limitation of using AF_PACKET to send packets.
> 
> Actually this update of network header to start of the IP header may
> have been a mistake. If userspace inserts a VLAN packet, that is what
> should enter the stack.
> 
> But for this specific issue: would it make sense to just move
> skb_probe_transport_header before that adjustment?

I think it is feasible. The transport_header will be set correctly, and other
behaviors will remain consistent with before, without introducing an
new issues.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-08-07  2:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-05 10:53 [PATCH net 0/2] net: fix skb->protocol not updated after VLAN network header adjustment wei.fang
2026-08-05 10:53 ` [PATCH net 1/2] net: packet: " wei.fang
2026-08-05 10:53 ` [PATCH net 2/2] net: tap: " wei.fang
2026-08-05 12:48   ` Willem de Bruijn
2026-08-06  2:10     ` Wei Fang
2026-08-06 10:06       ` Wei Fang
2026-08-06 14:12         ` Willem de Bruijn
2026-08-07  2:21           ` Wei Fang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox