From: Justin Iurman <justin.iurman@gmail.com>
To: Qanux <qjx1298677004@gmail.com>, netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, dsahern@kernel.org
Subject: Re: [PATCH net v2] ipv6: ioam: fix heap buffer overflow in __ioam6_fill_trace_data()
Date: Wed, 11 Feb 2026 21:20:56 +0100 [thread overview]
Message-ID: <86f924da-c742-44eb-aea4-9ac00a872198@gmail.com> (raw)
In-Reply-To: <20260211040412.86195-1-qjx1298677004@gmail.com>
On 2/11/26 05:04, Qanux wrote:
> On the receive path, __ioam6_fill_trace_data() uses trace->nodelen
> to decide how much data to write for each node. It trusts this field
> as-is from the incoming packet, with no consistency check against
> trace->type (the 24-bit field that tells which data items are
> present). A crafted packet can set nodelen=0 while setting type bits
> 0-21, causing the function to write ~100 bytes past the allocated
> region (into skb_shared_info), which corrupts adjacent heap memory
> and leads to a kernel panic.
>
> Add a shared helper ioam6_trace_compute_nodelen() in ioam6.c to
> derive the expected nodelen from the type field, and use it:
>
> - in ioam6_iptunnel.c (send path, existing validation) to replace
> the open-coded computation;
> - in exthdrs.c (receive path, ipv6_hop_ioam) to drop packets whose
> nodelen is inconsistent with the type field, before any data is
> written.
>
> Per RFC 9197, bits 12-21 are each short (4-octet) fields, so they
> are included in IOAM6_MASK_SHORT_FIELDS (changed from 0xff100000 to
> 0xff1ffc00).
>
> Fixes: 9ee11f0fff20 ("ipv6: ioam: Data plane support for Pre-allocated Trace")
> Cc: stable@vger.kernel.org
> Signed-off-by: Junxi Qian <qjx1298677004@gmail.com>
> ---
> v1 -> v2:
> - Don't recompute nodelen in the data plane; instead, validate
> nodelen consistency in ipv6_hop_ioam() on the receive path and
> drop inconsistent packets.
> - Add shared helper ioam6_trace_compute_nodelen() in ioam6.c,
> reuse it in both ioam6_iptunnel.c (send) and exthdrs.c (receive).
> - Per RFC 9197, include bits 12-21 in IOAM6_MASK_SHORT_FIELDS
> (0xff100000 -> 0xff1ffc00) instead of a separate UNDEF mask.
>
> Thanks to Justin Iurman for the detailed review and suggestions.
>
> The patch has been tested with the PoC that previously triggered the
> heap overflow. After applying this fix, the crafted packet is now
> correctly dropped at the receive path, and the kernel no longer panics.
> The patched kernel compiles and boots successfully.
> ---
> include/net/ioam6.h | 2 ++
> net/ipv6/exthdrs.c | 5 +++++
> net/ipv6/ioam6.c | 14 ++++++++++++++
> net/ipv6/ioam6_iptunnel.c | 10 +---------
> 4 files changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/include/net/ioam6.h b/include/net/ioam6.h
> index 2cbbee6e8..a75912fe2 100644
> --- a/include/net/ioam6.h
> +++ b/include/net/ioam6.h
> @@ -60,6 +60,8 @@ void ioam6_fill_trace_data(struct sk_buff *skb,
> struct ioam6_trace_hdr *trace,
> bool is_input);
>
> +u8 ioam6_trace_compute_nodelen(u32 trace_type);
> +
> int ioam6_init(void);
> void ioam6_exit(void);
>
> diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
> index a23eb8734..50062f98d 100644
> --- a/net/ipv6/exthdrs.c
> +++ b/net/ipv6/exthdrs.c
> @@ -930,6 +930,11 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff)
> if (hdr->opt_len < 2 + sizeof(*trace) + trace->remlen * 4)
> goto drop;
>
> + /* Inconsistent Pre-allocated Trace header */
> + if (trace->nodelen !=
> + ioam6_trace_compute_nodelen(be32_to_cpu(trace->type_be32)))
> + goto drop;
> +
> /* Ignore if the IOAM namespace is unknown */
> ns = ioam6_namespace(dev_net(skb->dev), trace->namespace_id);
> if (!ns)
> diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c
> index 9553a3200..08b7ac8c9 100644
> --- a/net/ipv6/ioam6.c
> +++ b/net/ipv6/ioam6.c
> @@ -690,6 +690,20 @@ struct ioam6_namespace *ioam6_namespace(struct net *net, __be16 id)
> return rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params);
> }
>
> +#define IOAM6_MASK_SHORT_FIELDS 0xff1ffc00
> +#define IOAM6_MASK_WIDE_FIELDS 0x00e00000
> +
> +u8 ioam6_trace_compute_nodelen(u32 trace_type)
> +{
> + u8 nodelen = hweight32(trace_type & IOAM6_MASK_SHORT_FIELDS)
> + * (sizeof(__be32) / 4);
> +
> + nodelen += hweight32(trace_type & IOAM6_MASK_WIDE_FIELDS)
> + * (sizeof(__be64) / 4);
> +
> + return nodelen;
> +}
> +
> static void __ioam6_fill_trace_data(struct sk_buff *skb,
> struct ioam6_namespace *ns,
> struct ioam6_trace_hdr *trace,
> diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c
> index 1fe7894f1..b9f6d892a 100644
> --- a/net/ipv6/ioam6_iptunnel.c
> +++ b/net/ipv6/ioam6_iptunnel.c
> @@ -22,9 +22,6 @@
> #include <net/ip6_route.h>
> #include <net/addrconf.h>
>
> -#define IOAM6_MASK_SHORT_FIELDS 0xff100000
> -#define IOAM6_MASK_WIDE_FIELDS 0xe00000
> -
> struct ioam6_lwt_encap {
> struct ipv6_hopopt_hdr eh;
> u8 pad[2]; /* 2-octet padding for 4n-alignment */
> @@ -93,13 +90,8 @@ static bool ioam6_validate_trace_hdr(struct ioam6_trace_hdr *trace)
> trace->type.bit21 | trace->type.bit23)
> return false;
>
> - trace->nodelen = 0;
> fields = be32_to_cpu(trace->type_be32);
> -
> - trace->nodelen += hweight32(fields & IOAM6_MASK_SHORT_FIELDS)
> - * (sizeof(__be32) / 4);
> - trace->nodelen += hweight32(fields & IOAM6_MASK_WIDE_FIELDS)
> - * (sizeof(__be64) / 4);
> + trace->nodelen = ioam6_trace_compute_nodelen(fields);
>
> return true;
> }
LGTM, thanks.
Reviewed-by: Justin Iurman <justin.iurman@gmail.com>
next prev parent reply other threads:[~2026-02-11 20:20 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-11 4:04 [PATCH net v2] ipv6: ioam: fix heap buffer overflow in __ioam6_fill_trace_data() Qanux
2026-02-11 20:20 ` Justin Iurman [this message]
2026-02-13 20:30 ` patchwork-bot+netdevbpf
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=86f924da-c742-44eb-aea4-9ac00a872198@gmail.com \
--to=justin.iurman@gmail.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=qjx1298677004@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox