From 238164201431a425e48dfcb8e9a59de63caf175b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 17 Oct 2026 12:42:28 +0200 Subject: [PATCH] ip6mr: clear skb->cb[] in reg_vif_xmit() reg_vif_xmit() hands the skb to ip6mr_cache_report() as an MRT6MSG_WHOLEPKT report. skb_realloc_headroom() copies skb->cb[] into the report, which is queued to the mroute socket, where rawv6_recvmsg() reads it as IP6CB. By the time the pim6reg device transmits the packet, skb->cb[] is not IP6CB anymore: qdisc_pkt_len_init() overwrites iif and ra, and any qdisc installed on the device (fq, fq_codel, pie, cake...) or a tc BPF program writing skb->cb[] fills the area holding dst0, srcrt, dst1, lastopt and flags. Since commit dd433671fef3 ("ipv6: validate extension header length before copying to cmsg") these stale offsets can no longer cause out-of-bounds reads, but the mroute socket can still receive bogus IPV6_PKTINFO ifindex and extension header ancillary data. Clear IP6CB before building the report. The skb is freed right after, so nothing else depends on its control block. Fixes: 14fb64e1f449 ("[IPV6] MROUTE: Support PIM-SM (SSM).") Signed-off-by: Eric Dumazet Signed-off-by: Jakub Kicinski --- net/ipv6/ip6mr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 36f117ad3670..3a551be30f15 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -653,6 +653,12 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, DEV_STATS_ADD(dev, tx_bytes, skb->len); DEV_STATS_INC(dev, tx_packets); + /* skb->cb[] holds qdisc/tc state at this point, not IP6CB. + * ip6mr_cache_report() copies it to the report delivered to + * the mroute socket, where it is read as IP6CB. + */ + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + ip6mr_cache_report(mrt, skb, READ_ONCE(mrt->mroute_reg_vif_num), MRT6MSG_WHOLEPKT); rcu_read_unlock();