linux/net/core
Artem Lytkin 51e15308c6 rtnetlink: cap IFLA_VFINFO_LIST at a documented number of VFs
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. The list dates back to commit
c02db8c629 ("rtnetlink: make SR-IOV VF interface symmetric") in 2010
and has never been able to describe an arbitrary number of VFs; nothing
regressed, the encoding simply cannot represent it.

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 ff205bf8c5 ("netlink: add one
debug check in nla_nest_end()").

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,
and on a kernel without CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS the
statistics carry a padding attribute each and cost 32 bytes more, making
those two 328 and 368. The nest therefore overflows somewhere between 179
and 335 VFs, and ice allows 256 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_cap() applies the cap in both places, so
rtnl_vfinfo_size() does not size the skb 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>
Link: https://patch.msgid.link/20260801114944.115272-1-iprintercanon@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-08-06 12:42:49 +02:00
..
bpf_sk_storage.c bpf: Fix UAF in sock clone early bailouts 2026-07-09 18:44:16 +02:00
datagram.c
dev_addr_lists_test.c net: cache snapshot entries for ndo_set_rx_mode_async 2026-04-21 12:50:13 +02:00
dev_addr_lists.c net: turn the rx_mode work into a generic netdev_work facility 2026-06-25 10:18:40 -07:00
dev_api.c net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work 2026-04-21 12:50:03 +02:00
dev_ioctl.c net: ethtool: make dev->hwprov ops-protected 2026-06-09 10:13:04 -07:00
dev.c net: pass dst via net_device_path in dev_fill_forward_path() 2026-07-31 14:47:03 +02:00
dev.h net: turn the rx_mode work into a generic netdev_work facility 2026-06-25 10:18:40 -07:00
devmem.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-05-21 15:09:02 -07:00
devmem.h net: devmem: support TX over NETMEM_TX_NO_DMA devices 2026-05-18 18:49:06 -07:00
drop_monitor.c drop_monitor: perform u64_stats updates under IRQ-disabled section 2026-07-23 11:00:01 -07:00
dst_cache.c
dst.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
failover.c net: failover: check register_netdevice_notifier() error in failover_init() 2026-08-04 18:46:34 -07:00
fib_notifier.c net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
fib_rules.c net: fib_rules: Destroy ops->lock in fib_rules_unregister(). 2026-07-07 10:51:06 +02:00
filter.c bpf: Reject redirect helpers without a bpf_net_context 2026-07-20 18:16:42 -07:00
flow_dissector.c flow_dissector: check device type before reading ETH_ADDRS 2026-06-18 18:07:00 -07:00
flow_offload.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
gen_estimator.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
gen_stats.c net/sched: add const qualifiers to gnet_stats helpers 2026-05-11 18:28:08 -07:00
gro_cells.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
gro.c net: gro: fix double aggregation of flush-marked skbs 2026-07-21 08:30:54 -07:00
gso.c
hotdata.c net: remove EXPORT_IPV6_MOD() and EXPORT_IPV6_MOD_GPL() macros 2026-03-29 11:21:22 -07:00
hwbm.c
ieee8021q_helpers.c
link_watch.c net: rename netdev_ops_assert_locked() 2026-06-04 14:04:55 -07:00
lock_debug.c net: require instance lock for NETDEV_DOWN/GOING_DOWN notifiers 2026-07-07 15:31:37 +02:00
lwt_bpf.c bpf: lwt: Fix dst reference leak on reroute failure 2026-07-28 13:22:11 +02:00
lwtunnel.c net: lwtunnel: Drop skb metadata before LWT encapsulation 2026-06-23 19:07:23 -07:00
Makefile net: turn the rx_mode work into a generic netdev_work facility 2026-06-25 10:18:40 -07:00
mp_dmabuf_devmem.h
neighbour.c neighbour: remove obsolete EXPORT_SYMBOL() 2026-06-08 15:59:17 -07:00
net_namespace.c net: Call unregister_netdevice_many() per netns. 2026-07-11 12:57:50 +02:00
net_test.c
net-procfs.c net: add proper RCU protection to /proc/net/ptype 2026-02-03 19:20:30 -08:00
net-sysfs.c rtnetlink: use dev_isalive() in rtnl_getlink() 2026-06-04 18:16:14 -07:00
net-sysfs.h net: add skb_defer_disable_key static key 2026-03-12 19:25:33 -07:00
net-traces.c
netclassid_cgroup.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
netdev_config.c net: add queue config validation callback 2026-01-23 11:49:02 -08:00
netdev_queues.c net: rename netdev_ops_assert_locked() 2026-06-04 14:04:55 -07:00
netdev_rx_queue.c net: Stop leased rxq before uninstalling its memory provider 2026-06-11 15:57:39 -07:00
netdev_work.c net: add the driver-facing netdev_work scheduling API 2026-06-25 10:18:40 -07:00
netdev-genl-gen.c net: devmem: allow bind-rx from non-init user namespaces 2026-06-05 18:10:31 -07:00
netdev-genl-gen.h net: Add queue-create operation 2026-04-09 18:21:45 -07:00
netdev-genl.c netdev-genl: report NAPI thread PID in the caller's pid namespace 2026-06-17 16:09:32 -07:00
netevent.c
netmem_priv.h Revert "mm: introduce a new page type for page pool in page type" 2026-05-21 19:06:13 -07:00
netpoll.c netconsole: move netpoll_wait_carrier() as netcons_wait_carrier() 2026-07-30 12:14:39 +02:00
netprio_cgroup.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
of_net.c
page_pool_priv.h
page_pool_user.c net: make page_pool_get_stats() void 2026-05-28 18:10:03 -07:00
page_pool.c net: make page_pool_get_stats() void 2026-05-28 18:10:03 -07:00
pktgen.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-07-30 12:53:19 -07:00
ptp_classifier.c
rtnetlink.c rtnetlink: cap IFLA_VFINFO_LIST at a documented number of VFs 2026-08-06 12:42:49 +02:00
scm.c net: use ktime_t in struct scm_timestamping_internal 2026-03-04 17:53:34 -08:00
secure_seq.c tcp: secure_seq: add back ports to TS offset 2026-03-04 17:44:35 -08:00
selftests.c net: Use helpers to get/set UDP len tree-wide 2026-07-22 13:47:02 +02:00
skb_fault_injection.c
skbuff.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-07-30 12:53:19 -07:00
skmsg.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2026-06-16 14:59:58 -07:00
sock_diag.c net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
sock_map.c bpf, sockmap: Reject unhashed UDP sockets on sockmap update 2026-07-15 10:34:14 +02:00
sock_reuseport.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
sock.c Lots of fixes, double the count even for the "new normal". 2026-07-23 12:58:08 -07:00
stream.c net: remove some unused EXPORT_SYMBOL()s 2026-06-12 16:43:11 -07:00
sysctl_net_core.c net: add skb_defer_disable_key static key 2026-03-12 19:25:33 -07:00
timestamping.c
tso.c net: Use helpers to get/set UDP len tree-wide 2026-07-22 13:47:02 +02:00
utils.c kernel.h: drop hex.h and update all hex.h users 2026-01-20 19:44:19 -08:00
xdp.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00