public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [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