From: Artem Lytkin <iprintercanon@gmail.com>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, jacob.e.keller@intel.com,
chrisw@sous-sol.org, linux-kernel@vger.kernel.org
Subject: [PATCH net] rtnetlink: truncate IFLA_VFINFO_LIST instead of overflowing its length
Date: Sat, 25 Jul 2026 16:22:36 +0300 [thread overview]
Message-ID: <20260725132236.88318-1-iprintercanon@gmail.com> (raw)
rtnl_fill_vf() closes the IFLA_VFINFO_LIST nest 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.
The skb is sized by if_nlmsg_size(), which adds rtnl_vfinfo_size() for
every VF, so the buffer really is large enough for the whole list and
none of the nla_put() calls in rtnl_fill_vfinfo() fails. The overflow is
therefore silent. Userspace then walks the message with RTA_NEXT(),
which advances by the stored length, so parsing resumes inside VF
payload and the top-level attributes that follow the nest are read out
of VF data. Those are IFLA_VF_PORTS, IFLA_XDP, IFLA_LINKINFO,
IFLA_PERM_ADDRESS and IFLA_PROP_LIST. iproute2 prints "!!!Deficit", and
strictly validating parsers reject the message outright.
rtnl_fill_vfinfo() emits 296 bytes per VF on a 64-bit kernel with
efficient unaligned access, so the nest wraps at 222 VFs; without
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS it is 328 bytes and 200 VFs, and
with ndo_get_vf_guid 336 bytes and 196 VFs. ice supports up to 256 VFs
per PF (ICE_MAX_SRIOV_VFS), so this is reachable on shipping hardware.
Requests that set RTEXT_FILTER_SKIP_STATS need 335 VFs, which the 256-VF
limit puts out of reach, so plain "ip link show" is fine today while
"ip -s link show" is not.
On CONFIG_DEBUG_NET kernels nla_nest_end() now also splats via
DEBUG_NET_WARN_ON_ONCE(), added along with nla_nest_end_safe() in commit
1346586a9ac9 ("netlink: add a nla_nest_end_safe() helper").
Using nla_nest_end_safe() here would not help: a nest that does not fit
in a u16 will not fit in a retried skb either, so returning -EMSGSIZE
would turn "ip link show" on such a device into a hard failure. Bound
the nest in the writer instead, as suggested when this was last
discussed: drop the VF that would push it past U16_MAX and end the list
there. Userspace sees IFLA_NUM_VF unchanged and a shorter
IFLA_VFINFO_LIST, and everything after the nest stays parsable. 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.
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.
Fixes: c02db8c6290b ("rtnetlink: make SR-IOV VF interface symmetric")
Reported-by: Jacob Keller <jacob.e.keller@intel.com>
Closes: 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>
---
net/core/rtnetlink.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 12aa3aa1688b1..bd1d65dcf42fd 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1687,10 +1687,22 @@ static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
return -EMSGSIZE;
for (i = 0; i < num_vfs; i++) {
+ unsigned char *mark = skb_tail_pointer(skb);
+
if (rtnl_fill_vfinfo(skb, dev, i, ext_filter_mask)) {
nla_nest_cancel(skb, vfinfo);
return -EMSGSIZE;
}
+
+ /* An attribute length is a u16, so the nest cannot describe
+ * more than U16_MAX bytes. Drop the VF that would overflow it
+ * and stop: a truncated list keeps the rest of the message
+ * parsable, whereas a wrapped nest length does not.
+ */
+ if (skb_tail_pointer(skb) - (unsigned char *)vfinfo > U16_MAX) {
+ nlmsg_trim(skb, mark);
+ break;
+ }
}
nla_nest_end(skb, vfinfo);
base-commit: 248951ddc14de84de3910f9b13f51491a8cd91df
--
2.43.0
next reply other threads:[~2026-07-25 13:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-25 13:22 Artem Lytkin [this message]
2026-07-30 1:55 ` [PATCH net] rtnetlink: truncate IFLA_VFINFO_LIST instead of overflowing its length 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 9:17 ` [PATCH net] rtnetlink: truncate IFLA_VFINFO_LIST instead of overflowing its length Jacob Keller
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=20260725132236.88318-1-iprintercanon@gmail.com \
--to=iprintercanon@gmail.com \
--cc=chrisw@sous-sol.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jacob.e.keller@intel.com \
--cc=kuba@kernel.org \
--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