All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Laight <david.laight.linux@gmail.com>
To: Daniel Borkmann <daniel@iogearbox.net>
Cc: kuba@kernel.org, edumazet@google.com, dsahern@kernel.org,
	tom@herbertland.com, willemdebruijn.kernel@gmail.com,
	idosch@nvidia.com, justin.iurman@gmail.com, pabeni@redhat.com,
	netdev@vger.kernel.org
Subject: Re: [PATCH net v3] ipv6: Implement limits on extension header parsing
Date: Mon, 27 Apr 2026 14:14:49 +0100	[thread overview]
Message-ID: <20260427141449.4bc90a28@pumpkin> (raw)
In-Reply-To: <20260427101318.750730-1-daniel@iogearbox.net>

On Mon, 27 Apr 2026 12:13:18 +0200
Daniel Borkmann <daniel@iogearbox.net> wrote:

> ipv6_{skip_exthdr,find_hdr}() and ip6_{tnl_parse_tlv_enc_lim,
> protocol_deliver_rcu}() iterate over IPv6 extension headers until they
> find a non-extension-header protocol or run out of packet data. The
> loops have no iteration counter, relying solely on the packet length
> to bound them. For a crafted packet with 8-byte extension headers
> filling a 64KB jumbogram, this means a worst case of up to ~8k
> iterations with a skb_header_pointer call each. ipv6_skip_exthdr(),
> for example, is used where it parses the inner quoted packet inside
> an incoming ICMPv6 error:
> 
>   - icmpv6_rcv
>     - checksum validation
>     - case ICMPV6_DEST_UNREACH
>       - icmpv6_notify
>         - pskb_may_pull()       <- pull inner IPv6 header
>         - ipv6_skip_exthdr()    <- iterates here
>         - pskb_may_pull()
>         - ipprot->err_handler() <- sk lookup
> 
> The per-iteration cost of ipv6_skip_exthdr itself is generally
> light, but skb_header_pointer becomes more costly on reassembled
> packets: the first ~1232 bytes of the inner packet are in the skb's
> linear area, but the remaining ~63KB are in the frag_list where
> skb_copy_bits is needed to read data.
> 
> Add a configurable limit via a new sysctl net.ipv6.max_ext_hdrs_number
> (default 8, minimum 1). All four extension header walking functions
> are bound by this limit. The sysctl is in line with commit 47d3d7ac656a
> ("ipv6: Implement limits on Hop-by-Hop and Destination options").
> As documented, init_net is used to derive max_ext_hdrs_number to
> be consistent given a net cannot always reliably be retrieved.
> 
> Note that the check in ip6_protocol_deliver_rcu() happens right
> before the goto resubmit, such that we don't have to have a test
> for ipv6_ext_hdr() in the fast-path.
> 
> There's an ongoing IETF draft-iurman-6man-eh-occurrences to enforce
> IPv6 extension headers ordering and occurrence. The latter also
> discusses security implications. As per RFC8200 section 4.1, the
> occurrence rules for extension headers provide a practical upper
> bound, thus 8 was used as the default.
> 
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> ---
>  v2->v3:
>    - Adding IP6SKB_HOPBYHOP coverage (Justin)
>    - I left the limit at 8 w/ sysctl, still feels the better
>      option to me if we can keep the worst-case more tightened
>  v1->v2:
>    - Set the default to 8 (Justin)
>    - Update IETF references (Justin)
>    - Add core path coverage as well (Justin)
...
> @@ -72,7 +74,9 @@ EXPORT_SYMBOL(ipv6_ext_hdr);
>  int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
>  		     __be16 *frag_offp)
>  {
> +	int exthdr_max = READ_ONCE(init_net.ipv6.sysctl.max_ext_hdrs_cnt);
>  	u8 nexthdr = *nexthdrp;
> +	int exthdr_cnt = 0;
>  
>  	*frag_offp = 0;
>  
> @@ -82,6 +86,8 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
>  
>  		if (nexthdr == NEXTHDR_NONE)
>  			return -1;
> +		if (unlikely(exthdr_cnt++ >= exthdr_max))
> +			return -1;

It would be better to decrement the count and error at zero.
		if (unlikely(--exthdr_max < 0))
			return -1;

	David


  reply	other threads:[~2026-04-27 13:14 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-27 10:13 [PATCH net v3] ipv6: Implement limits on extension header parsing Daniel Borkmann
2026-04-27 13:14 ` David Laight [this message]
2026-04-27 13:30   ` Daniel Borkmann
2026-04-27 20:14 ` Victor Nogueira
2026-04-28  6:02 ` kernel test robot

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=20260427141449.4bc90a28@pumpkin \
    --to=david.laight.linux@gmail.com \
    --cc=daniel@iogearbox.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=idosch@nvidia.com \
    --cc=justin.iurman@gmail.com \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=tom@herbertland.com \
    --cc=willemdebruijn.kernel@gmail.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.