CVE-2026-98619: net: ethtool: keep rtnl_lock for the ioctl self test
In the Linux kernel, the following vulnerability has been resolved:
net: ethtool: keep rtnllock for the ioctl self test
An offline self test that brings the interface down and back up with netifclose() / netifopen() requires rtnllock for both. Since the ethtool IOCTL path became rtnl-optional for ops-locked drivers, the ETHTOOLTEST ioctl runs holding only the netdev instance lock, so on an ops-locked driver the self test now tears the device down without rtnllock.
With lockdep this reproduces deterministically on every offline self test on such a driver; note the sole lock held is the instance lock, not rtnl:
WARNING: suspicious RCU usage net/core/netpoll.c:207 suspicious rcudereferenceprotected() usage! 1 lock held by ethtool/107: #0: (&dev->lock){+.+.}, at: devethtool Call Trace: netpollpolldisable devclosemany netifclosemany netifclose fbnicselftest devethtoollocked devethtool devioctl sockioctl x64sysioctl
Without lockdep the same condition trips ASSERTRTNL() in devclosemany() / devopen(); that check only samples the global rtnl state, so it can be masked by a concurrent rtnl holder, but the device is still being reconfigured without the lock it requires.
The ethtool selftest is a legacy ioctl-only command, so an ETHTOOLTEST case is only needed on the ioctl path. Add an opt-in bit for drivers whose self test needs rtnllock and set it on the ops-locked drivers whose offline self test tears the interface down and up:
- fbnic (ops-locked via queuemgmtops): fbnicselftest() offline path uses netifclose() / netifopen(). - bnxt (ops-locked via queuemgmtops): bnxtselftest() offline path goes through bnxtclosenic() / bnxthalfopennic() / bnxthalfclosenic() / bnxtopennic(), which close and reopen the device.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
Keep rtnl_lock held for the ethtool ETHTOOL_TEST ioctl self-test path on ops-locked drivers whose offline self-test uses netif_close() and netif_open(), including bnxt and fbnic.