Re: [PATCH net-next v10 00/10] ipv6: Address ext hdr DoS vulnerabilities

Justin Iurman
2026-05-05T17:11:29Z

On 5/4/26 20:51, Tom Herbert wrote:
> IPv6 extension headers are defined to be quite open ended with few
> limits. For instance, RFC8200 requires a receiver to process any
> number of extension headers in a packet in any order. This flexibility
> comes at the cost of a potential Denial of Service attack. The only
> thing that might mitigate the DoS attacks is the fact that packets
> with extension headers experience high drop rates on the Internet so
> that a DoS attack based on extension wouldn't be very effective at
> Internet scale.
>
> This patch set addresses some of the more egregious vulnerabilities
> of extension headers to DoS attack.
>
> - If sysctl.max_dst_opts_cnt or hbh_opts_cnt are set to 0 then that
> disallows packets with Destination Options or Hop-by-Hop Options even
> if the packet contain zero non-padding options
>
> - Add a case for IPV6_TLV_TNL_ENCAP_LIMIT in the switch on TLV type
> in ip6_parse_tlv function. This TLV is handled in tunnel processing,
> however it needs to be detected in ip6_parse_tlv to properly account
> for it as recognized non-padding option
>
> - Move IPV6_TLV_TNL_ENCAP_LIMIT to uapi/linux/in6.h so that all the
> TLV definitions are in one place
>
> - Set the default limits of non-padding Hop-by-Hop and Destination
> options to 2. This means that if a packet contains more then two
> non-padding options then it will be dropped. The previous limit
> was 8, but that was too liberal considering that the stack only
> support two Destination Options and the most Hop-by-Hop options
> likely to ever be in the same packet are IOAM and JUMBO. The limit
> can be increased via sysctl for private use and experimentation
>
> - Enforce RFC8200 recommended ordering of Extension Headers. This
> also enforces that any Extension Header occurs at most once
> in a packet except for Destination Options that may appear
> twice. The enforce_ext_hdr_order sysctl controls enforcement. If
> it's set to true then order is enforced, if it's set to false then
> neither order nor number of occurrences are enforced.
>
> The enforced ordering is:
>
> IPv6 header
> Hop-by-Hop Options header
> Destination Options before the Routing header
> Routing header
> Fragment header
> Authentication header
> Encapsulating Security Payload header
> Destination Options header
> Upper-Layer header
>
> --- Background
>
> We selected the default value of eight in RFC8504 based on an
> expectation that there might be new options defined and that the
> Internet would be fixed to reliably support extension headers
> including those with options. I do not believe either of those are
> going to happen.
>
> Hop-by-Hop Options are ostensibly the right way to do network to host
> and host to network signaling.The only HBH options that might get any
> substantial deployment are Router Alert option and IOAM. The Router
> Alert option is being deprecated and IOAM is at best a "nice to
> have". The best use case of Hop-by-Hop options is congestion
> signaling, unfortunately the die was cast when CSIG authors decided to
> place the information in VLANs at L2 and cajole the information to be
> routable through a switch. IMO, the miss on CSIG pretty much is the
> nail in the coffin for Hop-by-Hop options to ever be widely deployed
> (https://www.ietf.org/archive/id/draft-ravi-ippm-csig-01.txt).
>
> Destination Options have proven even less useful than Hop-by-Hop
> Options. The only Destination Options supported by the stack is the
> Tunnel Encap Limit option and Home Address Options. The Tunnel Encap
> Option was buried in the v6 tunnel code which is why it wasn't obvious
> it was supported in the first version of the patch set. I'll assume
> that might be useful, so this patch set cleans up the code for it. I
> don't believe there's any use of Home Address Option.
>
> A major problem with DestOpts, HBH, Routing Header, and Fragment
> header is that they have no inherent security. Their use presents a
> security risk especially when sent over untrusted networks including
> the Internet. Given that and that the high drop rates of extension
> headers on the Internet, I am proposing that Extension header except
> for ESP being deprecated on the Internet
> (https://www.ietf.org/archive/id/draft-herbert-deprecate-eh-01.txt).
>
> An update to RFC8200 is being proposed in IETF to allow enforcement of
> extension header ordering and number of occurences. An I-D is in
> https://www.ietf.org/archive/id/draft-iurman-6man-eh-occurrences-00.txt
>
> --- Testing
>
> Add selftest eh_limits.sh. Tested by running:
>
> $ sudo ./eh_limits.sh
> TEST: EH-limits - default sysctls [ OK ]
> TEST: EH-limits - modified sysctls [ OK ]
>
> Tests passed: 2
> Tests failed: 0
>
> $ sudo ./eh_limits.sh -v
>>>>>> Default
> TEST: Two non-padding options in HBH and DestOpts: Received as expected
> TEST: Big destination option: Received as expected
> TEST: Almost Big HBH option: Received as expected
> TEST: Big HBH option: Received as expected
> TEST: Too much HBH padding: Didn't receive as expected
> TEST: Too much DestOpt padding: Didn't receive as expected
> TEST: Too much DestOpt padding #2: Didn't receive as expected
> TEST: Too much DestOpt padding #3: Didn't receive as expected
> TEST: Almost too much DestOpt padding #2: Received as expected
> TEST: Two Dest Ops: Didn't receive as expected
> TEST: OOO Routing header: Didn't receive as expected
> TEST: Two Routing headers: Didn't receive as expected
> TEST: Two Destination options okay: Received as expected
> TEST: Two Destination options: Didn't receive as expected
> TEST: Two Destination options after RH: Didn't receive as expected
> TEST: Many EH OOO: Didn't receive as expected
> TEST: Two fragment Headers: Didn't receive as expected
>
> TEST: EH-limits - default sysctls [ OK ]
>>>>>> No order enforce, 8 options, 66 length limit
> TEST: Two non-padding options in HBH and DestOpts: Received as expected
> TEST: Big destination option: Didn't receive as expected
> TEST: Almost Big HBH option: Received as expected
> TEST: Big HBH option: Didn't receive as expected
> TEST: Too much HBH padding: Didn't receive as expected
> TEST: Too much DestOpt padding: Didn't receive as expected
> TEST: Too much DestOpt padding #2: Didn't receive as expected
> TEST: Too much DestOpt padding #3: Didn't receive as expected
> TEST: Almost too much DestOpt padding #2: Received as expected
> TEST: Two Dest Ops: Received as expected
> TEST: OOO Routing header: Received as expected
> TEST: Two Routing headers: Received as expected
> TEST: Two Destination options okay: Received as expected
> TEST: Two Destination options: Received as expected
> TEST: Two Destination options after RH: Received as expected
> TEST: Many EH OOO: Received as expected
> TEST: Two fragment Headers: Didn't receive as expected
>
> TEST: EH-limits - modified sysctls [ OK ]
>
> Tests passed: 2
> Tests failed: 0
>
> V4: Switch order of patches to avoid transient build failure
> V5: Allow Destination Options before the Routing header, fixes
> suggested by Justin Iurman
> v6: Fix a bug and create a test for extension header limits
> v7: Run pylint on new Python file, run shellcheck on new bash file,
> Make fixes as needed
> v8: Repost
> v9: Fix subject prefix
> v10: Lint fixes in selftest scripts suggested by Simon Horman
>
> Tom Herbert (10):
> ipv6: Check of max HBH or DestOp sysctl is zero and drop if it is
> ipv6: Cleanup IPv6 TLV definitions
> ipv6: Add case for IPV6_TLV_TNL_ENCAP_LIMIT in EH TLV switch
> ipv6: Set HBH and DestOpt limits to 2
> ipv6: Document defaults for max_{dst|hbh}_opts_number sysctls
> ipv6: Enforce Extension Header ordering
> ipv6: Document enforce_ext_hdr_order sysctl
> test: Add proto_nums.py in networking selftests
> test: Add ext_hdr.py in networking selftests
> test: Add networking selftest for eh limits
>
> Documentation/networking/ip-sysctl.rst | 52 ++-
> include/net/ipv6.h | 9 +-
> include/net/netns/ipv6.h | 1 +
> include/net/protocol.h | 14 +
> include/uapi/linux/in6.h | 21 +-
> include/uapi/linux/ip6_tunnel.h | 1 -
> net/ipv6/af_inet6.c | 1 +
> net/ipv6/exthdrs.c | 32 +-
> net/ipv6/ip6_input.c | 42 +++
> net/ipv6/reassembly.c | 1 +
> net/ipv6/sysctl_net_ipv6.c | 7 +
> net/ipv6/xfrm6_protocol.c | 2 +
> tools/testing/selftests/net/Makefile | 4 +
> tools/testing/selftests/net/eh_limits.py | 349 ++++++++++++++++++++
> tools/testing/selftests/net/eh_limits.sh | 210 ++++++++++++
> tools/testing/selftests/net/ext_hdr.py | 385 ++++++++++++++++++++++
> tools/testing/selftests/net/proto_nums.py | 231 +++++++++++++
> 17 files changed, 1334 insertions(+), 28 deletions(-)
> create mode 100755 tools/testing/selftests/net/eh_limits.py
> create mode 100755 tools/testing/selftests/net/eh_limits.sh
> create mode 100755 tools/testing/selftests/net/ext_hdr.py
> create mode 100644 tools/testing/selftests/net/proto_nums.py
>

Hi Tom,

While at it, should we also take care of ip6_tnl_parse_tlv_enc_lim(),
ipv6_skip_exthdr(), and ipv6_find_hdr(), so that we remain consistent
with recent merged fixes 3744b0964d52 and 076b8cad77aa ?

Cheers,
Justin