CVE-2026-46132
Description
In the Linux kernel, the following vulnerability has been resolved:
net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
rtnl_fill_vfinfo() declares struct ifla_vf_broadcast on the stack without initialisation:
struct ifla_vf_broadcast vf_broadcast;
The struct contains a single fixed 32-byte field:
/* include/uapi/linux/if_link.h */ struct ifla_vf_broadcast { __u8 broadcast[32]; };
The function then copies dev->broadcast into it using dev->addr_len as the length:
memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);
On Ethernet devices (the overwhelming majority of SR-IOV NICs) dev->addr_len is 6, so only the first 6 bytes of broadcast[] are written. The remaining 26 bytes retain whatever was previously on the kernel stack. The full struct is then handed to userspace via:
nla_put(skb, IFLA_VF_BROADCAST, sizeof(vf_broadcast), &vf_broadcast)
leaking up to 26 bytes of uninitialised kernel stack per VF per RTM_GETLINK request, repeatable.
The other vf_* structs in the same function are explicitly zeroed for exactly this reason - see the memset() calls for ivi, vf_vlan_info, node_guid and port_guid a few lines above. vf_broadcast was simply missed when it was added.
Reachability: any unprivileged local process can open AF_NETLINK / NETLINK_ROUTE without capabilities and send RTM_GETLINK with an IFLA_EXT_MASK attribute carrying RTEXT_FILTER_VF. The kernel walks each VF and emits IFLA_VF_BROADCAST, leaking 26 bytes of stack per VF per request. Stack residue at this call site can include return addresses and transient sensitive data; KASAN with stack instrumentation, or KMSAN, will flag the nla_put() when reproduced.
Zero the on-stack struct before the partial memcpy, matching the existing pattern used for the other vf_* structs in the same function.
Affected products
1Patches
100653c0516234net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
1 file changed · +1 −1
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index acb3a8e19743c3..350705730f76a1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1362,6 +1362,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
38bcc21f5224net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 69daba3ddaf06b..ad0c7b0b4a506e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 69daba3ddaf06b..ad0c7b0b4a506e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
c5b1b92ab7efnet: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 24722671cbed98..2176cd1bc765d1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1369,6 +1369,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 24722671cbed98..2176cd1bc765d1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1369,6 +1369,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
fbe0e6197225net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f4ed60bd9a2567..0a43c3881e3f88 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1566,6 +1566,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f4ed60bd9a2567..0a43c3881e3f88 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1566,6 +1566,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
4b9e32799181net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b613bb6e07df65..df042da422ef31 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b613bb6e07df65..df042da422ef31 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
fbe0e6197225net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f4ed60bd9a2567..0a43c3881e3f88 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1566,6 +1566,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f4ed60bd9a2567..0a43c3881e3f88 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1566,6 +1566,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
38bcc21f5224net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 69daba3ddaf06b..ad0c7b0b4a506e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 69daba3ddaf06b..ad0c7b0b4a506e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
0653c0516234net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index acb3a8e19743c3..350705730f76a1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1362,6 +1362,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index acb3a8e19743c3..350705730f76a1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1362,6 +1362,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
4b9e32799181net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b613bb6e07df65..df042da422ef31 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b613bb6e07df65..df042da422ef31 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
c5b1b92ab7efnet: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
2 files changed · +2 −2
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 24722671cbed98..2176cd1bc765d1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1369,6 +1369,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
net/core/rtnetlink.c+1 −1 modifieddiff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 24722671cbed98..2176cd1bc765d1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1369,6 +1369,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, port_guid.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + memset(&vf_broadcast, 0, sizeof(vf_broadcast)); memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing stack initialisation of `struct ifla_vf_broadcast` in `rtnl_fill_vfinfo()` causes up to 26 bytes of uninitialised kernel stack to be copied to userspace via netlink."
Attack vector
An unprivileged local process opens an `AF_NETLINK` / `NETLINK_ROUTE` socket (no capabilities required) and sends an `RTM_GETLINK` request with an `IFLA_EXT_MASK` attribute carrying `RTEXT_FILTER_VF`. The kernel's `rtnl_fill_vfinfo()` walks each Virtual Function (VF) and emits the `IFLA_VF_BROADCAST` netlink attribute containing the full 32-byte `struct ifla_vf_broadcast`. Because only the first 6 bytes are overwritten by the legitimate broadcast address, the remaining 26 bytes leak uninitialised kernel stack memory to the requesting userspace process. This is repeatable per VF per request.
Affected code
The vulnerability is in the `rtnl_fill_vfinfo()` function in `net/core/rtnetlink.c` [patch_id=2898429]. The function declares `struct ifla_vf_broadcast vf_broadcast` on the stack without initialisation, then performs a partial `memcpy` using `dev->addr_len` (typically 6 bytes for Ethernet), leaving the remaining 26 bytes of the 32-byte `broadcast[]` field uninitialised.
What the fix does
The patch adds a single line — `memset(&vf_broadcast, 0, sizeof(vf_broadcast));` — immediately before the `memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len)` call [patch_id=2898429]. This zeroes the entire 32-byte on-stack struct before the partial copy, ensuring that the 26 bytes not overwritten by the broadcast address are clean zeros rather than stale kernel stack data. This matches the existing pattern used for other `vf_*` structs (ivi, vf_vlan_info, node_guid, port_guid) in the same function, which were already explicitly zeroed.
Preconditions
- authThe attacker must be able to open an AF_NETLINK / NETLINK_ROUTE socket (no special capabilities required)
- configThe system must have at least one SR-IOV Virtual Function (VF) configured on a network device
- inputThe attacker sends an RTM_GETLINK request with IFLA_EXT_MASK carrying RTEXT_FILTER_VF
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/0653c0516234c8258975d268a749115fc0f0ff00nvd
- git.kernel.org/stable/c/38bcc21f52246badb3154b6158dcb381d98de011nvd
- git.kernel.org/stable/c/4b9e327991815e128ad3af75c3a04630a63ce3e0nvd
- git.kernel.org/stable/c/c5b1b92ab7eff1a6e8c507ddde6fd02fabd0cfa8nvd
- git.kernel.org/stable/c/fbe0e6197225e6a83cf113a67a4b425f8de0bcd5nvd
News mentions
0No linked articles in our index yet.