Netdev List
 help / color / mirror / Atom feed
From: Weiming Shi <bestswngs@gmail.com>
To: "David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>
Cc: netdev@vger.kernel.org, Xiang Mei <xmei5@asu.edu>,
	zjamg <ndaugoing@gmail.com>, Weiming Shi <bestswngs@gmail.com>,
	stable@vger.kernel.org, co+b3e1928dd33a1bd6@bugs.sh
Subject: [PATCH net] net: mpls: keep transport offsets valid across label changes
Date: Sun, 11 Oct 2026 12:14:37 +0800	[thread overview]
Message-ID: <20261011041436.1424222-2-bestswngs@gmail.com> (raw)

skb_mpls_push() and skb_mpls_pop() can leave a transport header at or
inside the moved MPLS header behind. Repeated pops then make
skb_transport_offset() negative; when a GSO skb is redirected to egress,
qdisc_pkt_len_segs_init() widens that offset, wraps its pull length, and
dereferences about 4 GiB past skb->data.

For tunnel GSO, qdisc_pkt_len_segs_init() uses the inner transport header
instead. skb_mpls_push() rejects encapsulated skbs because the networking
stack does not support simultaneous tunnel and MPLS GSO, but
skb_mpls_pop() did not. This leaves the same negative-offset path reachable
through stale inner metadata.

Align outer transport headers at or before the affected network header
with its new position while preserving valid later L4 offsets. Reject
encapsulated skbs from skb_mpls_pop(), matching skb_mpls_push(), and
refresh mac_len after a pop.

BUG: unable to handle page fault for address: ffffed10408b8e0b
Oops: Oops: 0000 [#1] SMP KASAN NOPTI
RIP: qdisc_pkt_len_segs_init (include/linux/tcp.h:31 net/core/dev.c:4193)
Call Trace:
 __dev_queue_xmit (net/core/dev.c:4835)
 tcf_mirred_to_dev (net/sched/act_mirred.c:242 net/sched/act_mirred.c:237 net/sched/act_mirred.c:328)
 tcf_mirred_act (net/sched/act_mirred.c:489)
 tcf_action_exec (include/net/tc_wrapper.h:59 net/sched/act_api.c:1162 net/sched/act_api.c:1136)
 tcf_classify (include/net/tc_wrapper.h:178 net/sched/cls_api.c:1779 net/sched/cls_api.c:1875)
 tc_run (net/core/dev.c:4463)
 __netif_receive_skb_core.constprop.0 (net/core/dev.c:4538 net/core/dev.c:6115)
 __netif_receive_skb_one_core (net/core/dev.c:6262)
 netif_receive_skb (net/core/dev.c:6377 net/core/dev.c:6463 net/core/dev.c:6522)
 tun_get_user (drivers/net/tun.c:1595 drivers/net/tun.c:2045)
 tun_chr_write_iter (drivers/net/tun.c:2091)
 vfs_write (fs/read_write.c:595 fs/read_write.c:687)
 ksys_write (fs/read_write.c:739)
 do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
 entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
Kernel panic - not syncing: Fatal exception in interrupt

Cc: stable@vger.kernel.org
Fixes: 48d2ab609b6b ("net: mpls: Fixups for GSO")
Reported-by: <co+b3e1928dd33a1bd6@bugs.sh>
Assisted-by: LLM
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
 net/core/skbuff.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index cc3b4b702..c09bb8ac2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -6612,6 +6612,7 @@ int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
 		  int mac_len, bool ethernet)
 {
 	struct mpls_shim_hdr *lse;
+	bool trans_update;
 	int err;
 
 	if (unlikely(!eth_p_mpls(mpls_proto)))
@@ -6630,11 +6631,15 @@ int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
 		skb_set_inner_protocol(skb, skb->protocol);
 	}
 
+	trans_update = skb_transport_header_was_set(skb) &&
+		       skb->transport_header <= skb->network_header;
 	skb_push(skb, MPLS_HLEN);
 	memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
 		mac_len);
 	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, mac_len);
+	if (trans_update)
+		skb->transport_header = skb->network_header;
 	skb_reset_mac_len(skb);
 
 	lse = mpls_hdr(skb);
@@ -6669,6 +6674,10 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,
 	if (unlikely(!eth_p_mpls(skb->protocol)))
 		return 0;
 
+	/* Networking stack does not allow simultaneous Tunnel and MPLS GSO. */
+	if (skb->encapsulation)
+		return -EINVAL;
+
 	err = skb_ensure_writable(skb, mac_len + MPLS_HLEN);
 	if (unlikely(err))
 		return err;
@@ -6680,6 +6689,10 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,
 	__skb_pull(skb, MPLS_HLEN);
 	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, mac_len);
+	if (skb_transport_header_was_set(skb) &&
+	    skb->transport_header <= skb->network_header)
+		skb->transport_header = skb->network_header;
+	skb_reset_mac_len(skb);
 
 	if (ethernet && mac_len >= ETH_HLEN) {
 		struct ethhdr *hdr;

             reply	other threads:[~2026-10-11  4:14 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-11  4:14 Weiming Shi [this message]
2026-10-12  4:17 ` [PATCH net] net: mpls: keep transport offsets valid across label changes netdev-bot+sashiko

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=20261011041436.1424222-2-bestswngs@gmail.com \
    --to=bestswngs@gmail.com \
    --cc=co+b3e1928dd33a1bd6@bugs.sh \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=ndaugoing@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=stable@vger.kernel.org \
    --cc=xmei5@asu.edu \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox