From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
To: Ilya Maximets <i.maximets@ovn.org>, netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>, Kees Cook <kees@kernel.org>,
"Gustavo A. R. Silva" <gustavoars@kernel.org>,
Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>,
linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org,
llvm@lists.linux.dev, Johan Thomsen <write@ownrisk.dk>
Subject: Re: [PATCH net] net: dst_metadata: fix false-positive memcpy overflow in tun_dst_unclone
Date: Wed, 17 Jun 2026 14:08:07 -0600 [thread overview]
Message-ID: <9e941b82-23d4-44e6-a240-b7949ace76ab@embeddedor.com> (raw)
In-Reply-To: <20260616100332.1308294-1-i.maximets@ovn.org>
Hi,
On 6/16/26 04:03, Ilya Maximets wrote:
> kmalloc_flex() in metadata_dst_alloc() sets __counted_by for the
> structure to the options_len, which is then initialized to zero.
> Later, we're initializing the structure by copying the tunnel info
> together with the options, and this triggers a warning for a potential
> memcpy overflow, since the compiler estimates that the options can't
> fit into the structure, even though the memory for them is actually
> allocated.
>
> memcpy: detected buffer overflow: 104 byte write of buffer size 96
> WARNING: CPU: X PID: Y at lib/string_helpers.c:1036 __fortify_report
> skb_tunnel_info_unclone+0x179/0x190
> geneve_xmit+0x7fe/0xe00
This warning has nothing to do with counted_by. See below for more
comments.
>
> The issue is triggered when built with clang and source fortification.
>
> Fix that by doing the copy in two stages: first - the main data with
> the options_len, then the options. This way the correct length should
> be known at the time of the copy.
>
> It would be better if the options_len never changed after allocation,
> but the allocation code is a little separate from the initialization
> and it would be awkward and potentially dangerous to return a struct
> with options_len set to a non-zero value from the metadata_dst_alloc().
>
> Another option would be to use ip_tunnel_info_opts_set(), but it is
> doing too many unnecessary operations for the use case here.
>
> Fixes: 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")
> Reported-by: Johan Thomsen <write@ownrisk.dk>
> Closes: https://lore.kernel.org/netdev/CAKv6aAM8_EWgXScnKmKYm_4SwGDVBK++dzfP+Y6msUXbp99QUw@mail.gmail.com/
> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
> ---
>
> Johan, if you can test this one in your setup as well, that would
> be great. Thanks.
>
> include/net/dst_metadata.h | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
> index 1fc2fb03ce3f..f45d1e3163f0 100644
> --- a/include/net/dst_metadata.h
> +++ b/include/net/dst_metadata.h
> @@ -164,8 +164,11 @@ static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
> if (!new_md)
> return ERR_PTR(-ENOMEM);
>
> - memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
> - sizeof(struct ip_tunnel_info) + md_size);
What's going on here is that, internally, fortified memcpy() retrieves
the destination size via __builtin_dynamic_object_size() in mode 1.
That is:
__builtin_dynamic_object_size(&new_md->u.tun_info, 1)
For the above case, Clang returns sizeof(new_md->u.tun_info) == 96.
So the warning is reporting that 104 bytes don't fit in an object of
size 96 bytes, regardless of any counted_by annotation or allocation.
Of course, in this case, the write of 104 bytes into new_md->u.tun_info
is intentional and controlled, but what if it weren't?
On the other hand, for this same case, GCC currently returns SIZE_MAX,
which translates to -1 inside fortified memcpy(). Thus, bounds-checking
is bypassed, which is why this warning doesn't show up with GCC.
However, this is a bug in GCC. We're already looking into that.
I think we've had just a handful of cases like this across the whole
kernel tree. We can deal with them as you did here (by directly copying
the composite structure first, and then using memcpy() to copy into the
flexible-array member). If these cases ever become more common, we
could create some kind of helper to do both things at once. :)
> + /* Copy in two stages to keep the __counted_by happy. */
So based on my comments above, this code comment is not correct.
> + new_md->u.tun_info = md_dst->u.tun_info;
This is fine.
> + memcpy(ip_tunnel_info_opts(&new_md->u.tun_info),
> + ip_tunnel_info_opts(&md_dst->u.tun_info), md_size);
Is ip_tunnel_info_opts() really needed here?
Probably this works just fine:
memcpy(new_md->u.tun_info.options, md_dst->u.tun_info.options, md_size);
-Gustavo
next prev parent reply other threads:[~2026-06-17 20:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-16 10:03 [PATCH net] net: dst_metadata: fix false-positive memcpy overflow in tun_dst_unclone Ilya Maximets
2026-06-17 20:08 ` Gustavo A. R. Silva [this message]
2026-06-17 22:01 ` Ilya Maximets
2026-06-17 22:59 ` Gustavo A. R. Silva
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=9e941b82-23d4-44e6-a240-b7949ace76ab@embeddedor.com \
--to=gustavo@embeddedor.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gustavoars@kernel.org \
--cc=horms@kernel.org \
--cc=i.maximets@ovn.org \
--cc=justinstitt@google.com \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=pabeni@redhat.com \
--cc=write@ownrisk.dk \
/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