* [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment @ 2026-04-20 19:32 Greg Kroah-Hartman 2026-04-21 4:52 ` Kuniyuki Iwashima 0 siblings, 1 reply; 4+ messages in thread From: Greg Kroah-Hartman @ 2026-04-20 19:32 UTC (permalink / raw) To: netdev Cc: linux-kernel, Greg Kroah-Hartman, David S. Miller, David Ahern, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, stable ipv6_rpl_srh_rcv() processes a Routing Protocol for LLNs Source Routing Header by decompressing it, swapping the next segment address into ipv6_hdr->daddr, recompressing, and pushing the new header back. The recompressed header can be larger than the original when the address-elision opportunities are worse after the swap. The function pulls (hdr->hdrlen + 1) << 3 bytes (the old header) and pushes (chdr->hdrlen + 1) << 3 + sizeof(ipv6hdr) bytes (the new header plus the IPv6 header). pskb_expand_head() is called to guarantee headroom only when segments_left == 0. A crafted SRH that loops back to the local host (each segment is a local address, so ip6_route_input() delivers it back to ipv6_rpl_srh_rcv()) with chdr growing on each pass exhausts headroom over several iterations. When skb_push() lands skb->data exactly at skb->head, skb_reset_network_header() stores 0, and skb_mac_header_rebuild()'s skb_set_mac_header(skb, -skb->mac_len) computes 0 + (u16)(-14) = 65522. The subsequent memmove writes 14 bytes at skb->head + 65522. Expand the head whenever there is insufficient room for the push, not only on the final segment. Cc: "David S. Miller" <davem@davemloft.net> Cc: David Ahern <dsahern@kernel.org> Cc: Eric Dumazet <edumazet@google.com> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Simon Horman <horms@kernel.org> Reported-by: Anthropic Cc: stable <stable@kernel.org> Assisted-by: gkh_clanker_t1000 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- net/ipv6/exthdrs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 95558fd6f447..d866ab011e0a 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -592,7 +592,9 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb) skb_pull(skb, ((hdr->hdrlen + 1) << 3)); skb_postpull_rcsum(skb, oldhdr, sizeof(struct ipv6hdr) + ((hdr->hdrlen + 1) << 3)); - if (unlikely(!hdr->segments_left)) { + if (unlikely(!hdr->segments_left || + skb_headroom(skb) < sizeof(struct ipv6hdr) + + ((chdr->hdrlen + 1) << 3))) { if (pskb_expand_head(skb, sizeof(struct ipv6hdr) + ((chdr->hdrlen + 1) << 3), 0, GFP_ATOMIC)) { __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS); -- 2.53.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment 2026-04-20 19:32 [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment Greg Kroah-Hartman @ 2026-04-21 4:52 ` Kuniyuki Iwashima 2026-04-21 5:50 ` Greg KH 0 siblings, 1 reply; 4+ messages in thread From: Kuniyuki Iwashima @ 2026-04-21 4:52 UTC (permalink / raw) To: gregkh Cc: davem, dsahern, edumazet, horms, kuba, linux-kernel, netdev, pabeni, stable From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Mon, 20 Apr 2026 21:32:25 +0200 > ipv6_rpl_srh_rcv() processes a Routing Protocol for LLNs Source Routing > Header by decompressing it, swapping the next segment address into > ipv6_hdr->daddr, recompressing, and pushing the new header back. The > recompressed header can be larger than the original when the > address-elision opportunities are worse after the swap. > > The function pulls (hdr->hdrlen + 1) << 3 bytes (the old header) and > pushes (chdr->hdrlen + 1) << 3 + sizeof(ipv6hdr) bytes (the new header > plus the IPv6 header). pskb_expand_head() is called to guarantee > headroom only when segments_left == 0. > > A crafted SRH that loops back to the local host (each segment is a local > address, so ip6_route_input() delivers it back to ipv6_rpl_srh_rcv()) > with chdr growing on each pass exhausts headroom over several > iterations. How could this occur.. ? Did AI generate a repro or just flagged the possibility ? ipv6_rpl_sr_hdr.hdrlen >> 3 is the size of addresses in the header and 1 >> 3 is the size of ipv6_rpl_sr_hdr itself, which is pulled into skb_headroom in ipv6_rthdr_rcv(). In ipv6_rpl_srh_rcv(), the number of addresses is calculated based on ipv6_rpl_sr_hdr.hdrlen, and when hdr->segments_left is not zero in the "if" below, the new header has the exact same size with the old header, so there should be no overflow. Also, before the "if", ipv6_rpl_srh_rcv() calls skb_pull(skb, ((hdr->hdrlen + 1) << 3)); and after that, skb_push(skb, ((chdr->hdrlen + 1) << 3) + sizeof(struct ipv6hdr)); and if we jump to the looped_back label, it calls skb_pull(skb, sizeof(struct ipv6hdr)); So, I think the same size are pulled and pushed for each iteration (except for segments_left == 0 case) even with local addresses. > When skb_push() lands skb->data exactly at skb->head, > skb_reset_network_header() stores 0, and skb_mac_header_rebuild()'s > skb_set_mac_header(skb, -skb->mac_len) computes 0 + (u16)(-14) = 65522. > The subsequent memmove writes 14 bytes at skb->head + 65522. > > Expand the head whenever there is insufficient room for the push, not > only on the final segment. > > Cc: "David S. Miller" <davem@davemloft.net> > Cc: David Ahern <dsahern@kernel.org> > Cc: Eric Dumazet <edumazet@google.com> > Cc: Jakub Kicinski <kuba@kernel.org> > Cc: Paolo Abeni <pabeni@redhat.com> > Cc: Simon Horman <horms@kernel.org> > Reported-by: Anthropic > Cc: stable <stable@kernel.org> > Assisted-by: gkh_clanker_t1000 > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > --- > net/ipv6/exthdrs.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c > index 95558fd6f447..d866ab011e0a 100644 > --- a/net/ipv6/exthdrs.c > +++ b/net/ipv6/exthdrs.c > @@ -592,7 +592,9 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb) > skb_pull(skb, ((hdr->hdrlen + 1) << 3)); > skb_postpull_rcsum(skb, oldhdr, > sizeof(struct ipv6hdr) + ((hdr->hdrlen + 1) << 3)); > - if (unlikely(!hdr->segments_left)) { > + if (unlikely(!hdr->segments_left || > + skb_headroom(skb) < sizeof(struct ipv6hdr) + > + ((chdr->hdrlen + 1) << 3))) { > if (pskb_expand_head(skb, sizeof(struct ipv6hdr) + ((chdr->hdrlen + 1) << 3), 0, > GFP_ATOMIC)) { > __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS); > -- > 2.53.0 > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment 2026-04-21 4:52 ` Kuniyuki Iwashima @ 2026-04-21 5:50 ` Greg KH 2026-04-21 7:48 ` Greg KH 0 siblings, 1 reply; 4+ messages in thread From: Greg KH @ 2026-04-21 5:50 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: davem, dsahern, edumazet, horms, kuba, linux-kernel, netdev, pabeni, stable On Tue, Apr 21, 2026 at 04:52:52AM +0000, Kuniyuki Iwashima wrote: > From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > Date: Mon, 20 Apr 2026 21:32:25 +0200 > > ipv6_rpl_srh_rcv() processes a Routing Protocol for LLNs Source Routing > > Header by decompressing it, swapping the next segment address into > > ipv6_hdr->daddr, recompressing, and pushing the new header back. The > > recompressed header can be larger than the original when the > > address-elision opportunities are worse after the swap. > > > > The function pulls (hdr->hdrlen + 1) << 3 bytes (the old header) and > > pushes (chdr->hdrlen + 1) << 3 + sizeof(ipv6hdr) bytes (the new header > > plus the IPv6 header). pskb_expand_head() is called to guarantee > > headroom only when segments_left == 0. > > > > A crafted SRH that loops back to the local host (each segment is a local > > address, so ip6_route_input() delivers it back to ipv6_rpl_srh_rcv()) > > with chdr growing on each pass exhausts headroom over several > > iterations. > > How could this occur.. ? Did AI generate a repro or just > flagged the possibility ? It generated a reproducer which caused a crash which made me have to create this patch. I'll dig it out of the huge pile of mess that was sent to me and get it into a form that I can reply here to. thanks, greg k-h ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment 2026-04-21 5:50 ` Greg KH @ 2026-04-21 7:48 ` Greg KH 0 siblings, 0 replies; 4+ messages in thread From: Greg KH @ 2026-04-21 7:48 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: davem, dsahern, edumazet, horms, kuba, linux-kernel, netdev, pabeni, stable On Tue, Apr 21, 2026 at 07:50:45AM +0200, Greg KH wrote: > On Tue, Apr 21, 2026 at 04:52:52AM +0000, Kuniyuki Iwashima wrote: > > From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > > Date: Mon, 20 Apr 2026 21:32:25 +0200 > > > ipv6_rpl_srh_rcv() processes a Routing Protocol for LLNs Source Routing > > > Header by decompressing it, swapping the next segment address into > > > ipv6_hdr->daddr, recompressing, and pushing the new header back. The > > > recompressed header can be larger than the original when the > > > address-elision opportunities are worse after the swap. > > > > > > The function pulls (hdr->hdrlen + 1) << 3 bytes (the old header) and > > > pushes (chdr->hdrlen + 1) << 3 + sizeof(ipv6hdr) bytes (the new header > > > plus the IPv6 header). pskb_expand_head() is called to guarantee > > > headroom only when segments_left == 0. > > > > > > A crafted SRH that loops back to the local host (each segment is a local > > > address, so ip6_route_input() delivers it back to ipv6_rpl_srh_rcv()) > > > with chdr growing on each pass exhausts headroom over several > > > iterations. > > > > How could this occur.. ? Did AI generate a repro or just > > flagged the possibility ? > > It generated a reproducer which caused a crash which made me have to > create this patch. I'll dig it out of the huge pile of mess that was > sent to me and get it into a form that I can reply here to. Ok, got the reproducer working, and it turns out that this patch does NOT fix the issue, I should have tested it better. Let me work some more on this thing, sorry for the broken submission. thanks, greg k-h ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-04-21 7:48 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-20 19:32 [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment Greg Kroah-Hartman 2026-04-21 4:52 ` Kuniyuki Iwashima 2026-04-21 5:50 ` Greg KH 2026-04-21 7:48 ` Greg KH
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox