public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Kuniyuki Iwashima <kuniyu@google.com>
To: gregkh@linuxfoundation.org
Cc: davem@davemloft.net, dsahern@kernel.org, edumazet@google.com,
	 horms@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org,
	 netdev@vger.kernel.org, pabeni@redhat.com, stable@kernel.org
Subject: Re: [PATCH net] ipv6: rpl: expand skb head when recompressed SRH grows, not only on last segment
Date: Tue, 21 Apr 2026 04:52:52 +0000	[thread overview]
Message-ID: <20260421045510.1546375-1-kuniyu@google.com> (raw)
In-Reply-To: <2026042024-cabbie-gills-9371@gregkh>

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
> 

  reply	other threads:[~2026-04-21  4:55 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
2026-04-21  5:50   ` Greg KH
2026-04-21  7:48     ` Greg KH

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=20260421045510.1546375-1-kuniyu@google.com \
    --to=kuniyu@google.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=stable@kernel.org \
    /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