From: Jakub Kicinski <kuba@kernel.org>
To: Artem Lytkin <iprintercanon@gmail.com>
Cc: netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, horms@kernel.org, donald.hunter@gmail.com,
jacob.e.keller@intel.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next v2] rtnetlink: cap IFLA_VFINFO_LIST at a documented number of VFs
Date: Thu, 30 Jul 2026 14:09:31 -0700 [thread overview]
Message-ID: <20260730140931.14d5bf4b@kernel.org> (raw)
In-Reply-To: <20260730090700.65867-1-iprintercanon@gmail.com>
On Thu, 30 Jul 2026 12:07:00 +0300 Artem Lytkin wrote:
> rtnl_fill_vf() emits one IFLA_VF_INFO per VF into the IFLA_VFINFO_LIST
> nest and closes it with nla_nest_end(), which stores the accumulated
> length into nla_len. That field is a u16, so a nest larger than 65535
> bytes is written truncated modulo 65536.
>
> Nothing catches it on the way. if_nlmsg_size() adds rtnl_vfinfo_size()
> for every VF, so the skb really is large enough and none of the nla_put()
> calls fails. Userspace then walks the message with RTA_NEXT(), which
> advances by the stored length, so parsing resumes inside VF payload and
> the attributes after the nest are read out of VF data: IFLA_VF_PORTS,
> IFLA_XDP, IFLA_LINKINFO, IFLA_PERM_ADDRESS, IFLA_AF_SPEC. iproute2
> prints "!!!Deficit" and strictly validating parsers reject the message.
> On CONFIG_DEBUG_NET kernels nla_nest_end() also splats, via the
> DEBUG_NET_WARN_ON_ONCE() added in commit 1346586a9ac9 ("netlink: add a
> nla_nest_end_safe() helper").
>
> Where the wrap falls depends on what was asked for and on the host. A VF
> costs 196 bytes, 296 with statistics, 236 with GUIDs and 336 with both.
> On a kernel without CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS the statistics
> carry a padding attribute each and cost 32 bytes more, which makes those
> two 328 and 368. So the nest overflows somewhere between 179 and 335
> VFs. ice allows 256 VFs per PF
> (ICE_MAX_SRIOV_VFS), which reaches it. Statistics are included unless the
> request sets RTEXT_FILTER_SKIP_STATS, so the common case is the one that
> wraps first.
>
> A limit that moves with the requested attribute set and with the host's
> alignment requirements is not something userspace can be told, so use
> fixed numbers instead and document them as what the interface supports:
> 256 VFs, or 128 when statistics are included. Both stay well inside
> U16_MAX even in the largest per-VF encoding, at 60416 and 47104 bytes
> respectively. rtnl_vfinfo_size() applies the same limit so that the skb
> is not sized for VFs that will not be emitted.
>
> A device with more VFs than the limit reports a shorter
> IFLA_VFINFO_LIST. IFLA_NUM_VF keeps carrying the real count, and
> everything after the nest stays parsable, which is the part that is
> broken today. An empty nest is already emitted for a PF with no VFs, so a
> list shorter than IFLA_NUM_VF is not a new encoding.
>
> Returning -EMSGSIZE instead, which is what nla_nest_end_safe() would
> give, is not an option here: a nest that does not fit in a u16 will not
> fit in a retried skb either, so it would turn a link dump on such a
> device into a hard failure.
>
> The other large nests in rtnl_fill_ifinfo() were audited and cannot
> overflow. IFLA_AF_SPEC is bounded by a handful of address families at
> about a kilobyte each, and IFLA_VF_PORTS would need more than 560 VFs,
> which no in-tree driver allows.
>
> Reported-by: Jacob Keller <jacob.e.keller@intel.com>
> Link: https://lore.kernel.org/netdev/16b289f6-b025-5dd3-443d-92d4c167e79c@intel.com/
> Assisted-by: Claude:claude-fable-5
> Signed-off-by: Artem Lytkin <iprintercanon@gmail.com>
> ---
> v2:
> - cap at fixed limits, 256 VFs and 128 when statistics are included, and
> document them in the netlink spec, rather than dropping whichever VF
> happens not to fit (Jakub)
> - drop the Fixes: tag, this is a long standing limitation of the
> interface and not a regression (Jakub)
> - retarget net-next for the same reason
> - changelog: corrected the per-VF sizes, which mixed two configurations,
> and dropped IFLA_PROP_LIST from the list of attributes that follow the
> nest, since it is emitted before it
> v1: https://lore.kernel.org/netdev/20260725132236.88318-1-iprintercanon@gmail.com/
>
> Documentation/netlink/specs/rt-link.yaml | 5 +++++
> net/core/rtnetlink.c | 25 +++++++++++++++++++++++-
> 2 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/netlink/specs/rt-link.yaml b/Documentation/netlink/specs/rt-link.yaml
> index 68c26a70bb649..b80c2ac3ac311 100644
> --- a/Documentation/netlink/specs/rt-link.yaml
> +++ b/Documentation/netlink/specs/rt-link.yaml
> @@ -928,6 +928,11 @@ attribute-sets:
> name: vfinfo-list
> type: nest
> nested-attributes: vfinfo-list-attrs
> + doc: |
> + Per-VF details. The list holds at most 256 VFs, or 128 when
> + statistics are included, because it is one attribute and has to fit
> + in a u16 length. A device with more VFs than that reports a
> + truncated list; num-vf still carries the real count.
> -
> name: stats64
> type: binary
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 31c65a545a107..6395ea6701210 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1174,12 +1174,30 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
> a->rx_nohandler = b->rx_nohandler;
> }
>
> +/* IFLA_VFINFO_LIST is one netlink attribute, so everything nested inside it
> + * has to fit in the u16 nla_len. Bound the number of VFs described there at a
> + * fixed value rather than at whatever happens to fit, so that the limit is a
> + * property of the interface instead of one of the requested attribute set and
> + * the host's alignment requirements. The largest per-VF encoding is 368 bytes
> + * with statistics and GUIDs and 236 bytes without statistics, so both limits
> + * keep the nest well inside U16_MAX.
> + */
> +#define RTNL_VFINFO_MAX_VFS 256
> +#define RTNL_VFINFO_MAX_VFS_STATS 128
No strong opinion which to choose but I'd either move these defines
somewhere visible or just use the literal values. There's a common
fallacy that all literals must have defines, IMO if the literal is only
used once, by a small well scoped helper (here rtnl_vfinfo_max_vfs())
there's no ambiguity. The define is an extra indirection obfuscating
the code.
If you don't care either way either - I'd do the literal thing, and
let the comment describe the helper
> +static int rtnl_vfinfo_max_vfs(u32 ext_filter_mask)
if you pass the "real" num_vfs in here you can also subsume the min()
into the helper. Perhaps the helper should then be renamed s/_max/_cap/
> +{
> + return ext_filter_mask & RTEXT_FILTER_SKIP_STATS ?
> + RTNL_VFINFO_MAX_VFS : RTNL_VFINFO_MAX_VFS_STATS;
> +}
Other than that LGTM. Please send v3 as a new thread, not in reply to.
And FWIW (sorry, Im going to reply here to avoid splintering) I maintain
that net-next is better :) We are capping, who knows is someone
complains. So I _don't_ want this in LTS.
next prev parent reply other threads:[~2026-07-30 21:09 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-25 13:22 [PATCH net] rtnetlink: truncate IFLA_VFINFO_LIST instead of overflowing its length Artem Lytkin
2026-07-30 1:55 ` Jakub Kicinski
2026-07-30 9:07 ` [PATCH net-next v2] rtnetlink: cap IFLA_VFINFO_LIST at a documented number of VFs Artem Lytkin
2026-07-30 21:09 ` Jakub Kicinski [this message]
2026-07-30 23:14 ` Jacob Keller
2026-07-30 9:17 ` [PATCH net] rtnetlink: truncate IFLA_VFINFO_LIST instead of overflowing its length Jacob Keller
2026-07-30 17:12 ` Artem Lytkin
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=20260730140931.14d5bf4b@kernel.org \
--to=kuba@kernel.org \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=iprintercanon@gmail.com \
--cc=jacob.e.keller@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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