In ipv6_rpl_srh_rcv(), after pulling the compressed RPL SRH and calling skb_push(skb, chdr_len) to expand the buffer for the decompressed SRH, the function calls skb_mac_header_rebuild(skb) BEFORE copying the saved IPv6 header from oldhdr to ipv6_hdr(skb). When chdr_len - pull_len < skb->mac_len (for example, an 8-byte expansion with a 14-byte Ethernet MAC header), the newly rebuilt MAC header at [skb->data - skb->mac_len, skb->data) overlaps with the old IPv6 header at [oldhdr, oldhdr + 40). Calling skb_mac_header_rebuild(skb) first overwrites the beginning of oldhdr (version, traffic class, flow label, payload_len, nexthdr, hop_limit, and the start of saddr) with the Ethernet header bytes, and the subsequent memmove(ipv6_hdr(skb), oldhdr, sizeof(struct ipv6hdr)) copies those corrupted bytes into the new IPv6 header. Moreover, oldhdr's nexthdr is only updated to NEXTHDR_ROUTING before the pull, which also gets clobbered by the overlapping MAC rebuild. Fix this by copying the 40-byte IPv6 header from oldhdr to skb->data immediately after skb_push(skb, chdr_len) and before calling skb_reset_network_header(skb) and skb_mac_header_rebuild(skb), and explicitly setting ipv6_hdr(skb)->nexthdr = NEXTHDR_ROUTING. Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr") Assisted-by: LLM Signed-off-by: Hui Peng --- net/ipv6/exthdrs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 09a4552f7f08..f9563294c5b9 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -598,11 +598,12 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev) oldhdr = ipv6_hdr(skb); } skb_push(skb, chdr_len); + memmove(skb->data, oldhdr, sizeof(struct ipv6hdr)); skb_reset_network_header(skb); skb_mac_header_rebuild(skb); skb_set_transport_header(skb, sizeof(struct ipv6hdr)); + ipv6_hdr(skb)->nexthdr = NEXTHDR_ROUTING; - memmove(ipv6_hdr(skb), oldhdr, sizeof(struct ipv6hdr)); memcpy(skb_transport_header(skb), chdr, (chdr->hdrlen + 1) << 3); ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); -- 2.55.0.1082.g2b9226bbc0-goog