From: Jakub Kicinski <kuba@kernel.org> Date: 2026-09-03 03:26:19
Looking thru some reports prompted by:
Add new way to add BPF LSM hooks
https://lore.kernel.org/20260831110934.241898-1-a.s.protopopov@gmail.com
I/Claude noticed 3 drivers with buggy n-tuple filter dump. PoC built
based on intentionally adding the same bug in fbnic under QEMU confirms:
# install 8 rules (this part does need CAP_NET_ADMIN)
for p in 100 101 102 103 104 105 106 107; do
ethtool -N eth0 flow-type tcp4 dst-port $p action 0
done
# Python
SIOCETHTOOL = 0x8946
ETHTOOL_GRXCLSRLALL = 0x30
RXNFC_SIZE = 192 # sizeof(struct ethtool_rxnfc)
RULE_CNT_OFF = 184 # offsetof(struct ethtool_rxnfc, rule_cnt)
buf = array.array('B', bytes(RXNFC_SIZE + 4096))
struct.pack_into('=I', buf, 0, ETHTOOL_GRXCLSRLALL)
struct.pack_into('=I', buf, RULE_CNT_OFF, 1) # room for one location
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ifr = struct.pack('16sP', b'eth0', buf.buffer_info()[0])
fcntl.ioctl(sock, SIOCETHTOOL, ifr)
==================================================================
BUG: KASAN: slab-out-of-bounds in fbnic_get_rxnfc+0x144d/0x1910
Write of size 4 at addr ff11000007522be4 by task python3.12/647
Fix the 3 drivers, add a hopefully clearer mention in the doc.
Note that Sashiko will likely complain about mv88e6xxx letting
user read and delete rules from any port with ant netdev.
We can fix that in net-next, if mv88e6xxx experts can confirm that
the current behavior is not intentional (it's wrong but users may
now depend on it).
Jakub Kicinski (5):
net: dsa: bcm_sf2: bound the CFP rule dump by the caller's buffer size
eth: nfp: bound the ntuple rule dump by the caller's buffer size
eth: nfp: drop the replaced rule from the list when reprogramming
fails
net: dsa: mv88e6xxx: bound the policy rule dump by the caller's buffer
size
ethtool: document that GRXCLSRLALL rule_cnt is a caller-provided limit
include/linux/ethtool.h | 6 ++++++
drivers/net/dsa/bcm_sf2_cfp.c | 2 ++
drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++++++++----
.../ethernet/netronome/nfp/nfp_net_ethtool.c | 19 +++++++++++++++----
4 files changed, 35 insertions(+), 8 deletions(-)
--
2.55.0
From: Jakub Kicinski <kuba@kernel.org> Date: 2026-09-03 03:26:19
bcm_sf2_cfp_rule_get_all() walks the whole cfp.unique bitmap into
rule_locs[] without consulting nfc->rule_cnt, which is how many entries
the caller had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN
and the ioctl sizes the buffer from the rule_cnt userspace passes in, so
once an admin has installed CFP rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Fixes: 7318166cacad ("net: dsa: bcm_sf2: Add support for ethtool::rxnfc")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: florian.fainelli@broadcom.com
CC: jonas.gorski@gmail.com
CC: andrew@lunn.ch
CC: olteanv@gmail.com
---
drivers/net/dsa/bcm_sf2_cfp.c | 2 ++
1 file changed, 2 insertions(+)
From: Jakub Kicinski <kuba@kernel.org> Date: 2026-09-03 03:26:20
nfp_net_get_fs_loc() dumps every entry of nn->fs.list into rule_locs[]
without consulting cmd->rule_cnt, which is how many entries the caller
had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN and the
ioctl sizes the buffer from the rule_cnt userspace passes in, so once an
admin has installed flow steering rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Bail out with -EMSGSIZE when the buffer fills up, the way the other
ntuple capable drivers do, and report how many locations were filled so
a shrinking rule list does not leave the caller reading stale slots.
Reported-by: VEGA <redacted>
Fixes: 9eb03bb1c035 ("nfp: add ethtool flow steering callbacks")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: leitao@debian.org
CC: louis.peens@corigine.com
CC: yinjun.zhang@corigine.com
CC: oss-drivers@corigine.com
---
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
From: Jakub Kicinski <kuba@kernel.org> Date: 2026-09-03 03:26:20
nfp_net_fs_add() replaces an existing rule by deleting it from the
hardware, decrementing nn->fs.count and programming the new one. If
nfp_net_fs_add_hw() fails the old entry stays on nn->fs.list - only the
success path reaches list_replace() - so the list is one longer than
nn->fs.count, and it advertises a rule whose hardware entry has already
been torn down.
nn->fs.count is what ETHTOOL_GRXCLSRLCNT reports, so userspace then sizes
its buffer one entry short of what the GRXCLSRLALL walk wants to write.
That used to overwrite one u32 past the allocation; since the walk is
bounded it is a permanent -EMSGSIZE instead, as nothing ever resyncs the
counter.
Fixes: 9eb03bb1c035 ("nfp: add ethtool flow steering callbacks")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: leitao@debian.org
CC: yinjun.zhang@corigine.com
CC: louis.peens@corigine.com
CC: oss-drivers@corigine.com
---
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
@@ -1703,8 +1703,14 @@ static int nfp_net_fs_add(struct nfp_net *nn, struct ethtool_rxnfc *cmd)nn->fs.count--;err=nfp_net_fs_add_hw(nn,new);-if(err)+if(err){+/* mbox broken, adding the old rule back will+*likelyalsofail.+*/+list_del(&entry->node);+kfree(entry);gotoerr;+}nn->fs.count++;list_replace(&entry->node,&new->node);
From: Jakub Kicinski <kuba@kernel.org> Date: 2026-09-03 03:26:21
mv88e6xxx_get_rxnfc() uses rxnfc->rule_cnt as the write index while
dumping the policy IDR, clobbering the input value before it has been
looked at. That input is the number of entries the caller had room for.
ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN and the ioctl sizes the
buffer from the rule_cnt userspace passes in, so once an admin has
installed policy rules any user can ask for fewer slots than there are
rules and run off the end of the allocation. A rule_cnt of 0 leaves the
buffer pointer NULL and the walk dereferences it.
Count into a local so the caller's limit survives the walk, and stop with
-EMSGSIZE once it is reached.
Fixes: da7dc8755304 ("net: dsa: mv88e6xxx: add RXNFC support")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: andrew@lunn.ch
CC: olteanv@gmail.com
CC: vivien.didelot@gmail.com
CC: f.fainelli@gmail.com
---
drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
From: Jakub Kicinski <kuba@kernel.org> Date: 2026-09-03 03:26:21
Three drivers have shipped a get_rxnfc() which dumps its entire rule
table into rule_locs, reading rule_cnt as "how many rules do I have"
rather than "how many entries did the caller allocate". Nothing in the
callback's documentation contradicted that reading. The distinction only
matters because the ioctl lets an unprivileged caller pick rule_cnt
directly, so getting it wrong is a heap overflow rather than a truncated
dump.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: andrew@lunn.ch
---
include/linux/ethtool.h | 6 ++++++
1 file changed, 6 insertions(+)
From: Jonas Gorski <jonas.gorski@gmail.com> Date: 2026-09-03 08:30:30
On Thu, Sep 3, 2026 at 5:26 AM Jakub Kicinski [off-list ref] wrote:
bcm_sf2_cfp_rule_get_all() walks the whole cfp.unique bitmap into
rule_locs[] without consulting nfc->rule_cnt, which is how many entries
the caller had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN
and the ioctl sizes the buffer from the rule_cnt userspace passes in, so
once an admin has installed CFP rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Fixes: 7318166cacad ("net: dsa: bcm_sf2: Add support for ethtool::rxnfc")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: florian.fainelli@broadcom.com
CC: jonas.gorski@gmail.com
CC: andrew@lunn.ch
CC: olteanv@gmail.com
Reviewed-by: Jonas Gorski <jonas.gorski@gmail.com>
Best regards,
Jonas
bcm_sf2_cfp_rule_get_all() walks the whole cfp.unique bitmap into
rule_locs[] without consulting nfc->rule_cnt, which is how many entries
the caller had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN
and the ioctl sizes the buffer from the rule_cnt userspace passes in, so
once an admin has installed CFP rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Fixes: 7318166cacad ("net: dsa: bcm_sf2: Add support for ethtool::rxnfc")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
We had the exact same internal patch we were about to submit, thanks!
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
From: Joe Damato <hidden> Date: 2026-09-03 20:12:45
On Wed, Sep 02, 2026 at 08:26:07PM -0700, Jakub Kicinski wrote:
bcm_sf2_cfp_rule_get_all() walks the whole cfp.unique bitmap into
rule_locs[] without consulting nfc->rule_cnt, which is how many entries
the caller had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN
and the ioctl sizes the buffer from the rule_cnt userspace passes in, so
once an admin has installed CFP rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Fixes: 7318166cacad ("net: dsa: bcm_sf2: Add support for ethtool::rxnfc")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: florian.fainelli@broadcom.com
CC: jonas.gorski@gmail.com
CC: andrew@lunn.ch
CC: olteanv@gmail.com
---
drivers/net/dsa/bcm_sf2_cfp.c | 2 ++
1 file changed, 2 insertions(+)
From: Joe Damato <hidden> Date: 2026-09-03 20:14:09
On Wed, Sep 02, 2026 at 08:26:08PM -0700, Jakub Kicinski wrote:
nfp_net_get_fs_loc() dumps every entry of nn->fs.list into rule_locs[]
without consulting cmd->rule_cnt, which is how many entries the caller
had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN and the
ioctl sizes the buffer from the rule_cnt userspace passes in, so once an
admin has installed flow steering rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Bail out with -EMSGSIZE when the buffer fills up, the way the other
ntuple capable drivers do, and report how many locations were filled so
a shrinking rule list does not leave the caller reading stale slots.
Reported-by: VEGA <redacted>
Fixes: 9eb03bb1c035 ("nfp: add ethtool flow steering callbacks")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: leitao@debian.org
CC: louis.peens@corigine.com
CC: yinjun.zhang@corigine.com
CC: oss-drivers@corigine.com
---
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
From: Joe Damato <hidden> Date: 2026-09-03 20:16:46
On Wed, Sep 02, 2026 at 08:26:11PM -0700, Jakub Kicinski wrote:
Three drivers have shipped a get_rxnfc() which dumps its entire rule
table into rule_locs, reading rule_cnt as "how many rules do I have"
rather than "how many entries did the caller allocate". Nothing in the
callback's documentation contradicted that reading. The distinction only
matters because the ioctl lets an unprivileged caller pick rule_cnt
directly, so getting it wrong is a heap overflow rather than a truncated
dump.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: andrew@lunn.ch
---
include/linux/ethtool.h | 6 ++++++
1 file changed, 6 insertions(+)
From: Joe Damato <hidden> Date: 2026-09-03 20:20:15
On Wed, Sep 02, 2026 at 08:26:10PM -0700, Jakub Kicinski wrote:
mv88e6xxx_get_rxnfc() uses rxnfc->rule_cnt as the write index while
dumping the policy IDR, clobbering the input value before it has been
looked at. That input is the number of entries the caller had room for.
ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN and the ioctl sizes the
buffer from the rule_cnt userspace passes in, so once an admin has
installed policy rules any user can ask for fewer slots than there are
rules and run off the end of the allocation. A rule_cnt of 0 leaves the
buffer pointer NULL and the walk dereferences it.
Count into a local so the caller's limit survives the walk, and stop with
-EMSGSIZE once it is reached.
Fixes: da7dc8755304 ("net: dsa: mv88e6xxx: add RXNFC support")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: andrew@lunn.ch
CC: olteanv@gmail.com
CC: vivien.didelot@gmail.com
CC: f.fainelli@gmail.com
---
drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
From: Joe Damato <hidden> Date: 2026-09-03 20:32:36
On Wed, Sep 02, 2026 at 08:26:09PM -0700, Jakub Kicinski wrote:
nfp_net_fs_add() replaces an existing rule by deleting it from the
hardware, decrementing nn->fs.count and programming the new one. If
nfp_net_fs_add_hw() fails the old entry stays on nn->fs.list - only the
success path reaches list_replace() - so the list is one longer than
nn->fs.count, and it advertises a rule whose hardware entry has already
been torn down.
nn->fs.count is what ETHTOOL_GRXCLSRLCNT reports, so userspace then sizes
its buffer one entry short of what the GRXCLSRLALL walk wants to write.
That used to overwrite one u32 past the allocation; since the walk is
bounded it is a permanent -EMSGSIZE instead, as nothing ever resyncs the
counter.
Fixes: 9eb03bb1c035 ("nfp: add ethtool flow steering callbacks")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: leitao@debian.org
CC: yinjun.zhang@corigine.com
CC: louis.peens@corigine.com
CC: oss-drivers@corigine.com
---
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski [off-list ref]:
On Wed, 2 Sep 2026 20:26:06 -0700 you wrote:
Looking thru some reports prompted by:
Add new way to add BPF LSM hooks
https://lore.kernel.org/20260831110934.241898-1-a.s.protopopov@gmail.com
I/Claude noticed 3 drivers with buggy n-tuple filter dump. PoC built
based on intentionally adding the same bug in fbnic under QEMU confirms:
[...]