Thread (2 messages) 2 messages, 2 authors, 2026-03-11

BUG: unable to handle kernel NULL pointer dereference in __ethtool_get_link_ksettings

From: Jianzhou Zhao <hidden>
Date: 2026-03-11 08:12:48
Also in: lkml


Subject: [BUG] net: kernel NULL pointer dereference in __ethtool_get_link_ksettings

Dear Maintainers,

We are writing to report a NULL pointer dereference vulnerability within the `__ethtool_get_link_ksettings()` function. This bug was found by our custom fuzzing tool, RacePilot. The bug occurs when an internal subsystem (e.g., `smc` routing or `infiniband` querying a hardware port) attempts to retrieve the link speed of an `ipvlan` interface that is layered on top of a virtual or device hierarchy lacking `ethtool_ops`. We observed this bug on the Linux kernel version 6.18.0-08691-g2061f18ad76e-dirty.

Call Trace & Context
==================================================================
BUG: kernel NULL pointer dereference, address: 00000000000001f8
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0 
Oops: Oops: 0000 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 8322 Comm: kworker/0:9 Not tainted 6.18.0-08691-g2061f18ad76e-dirty #50 PREEMPT(voluntary) 
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Workqueue: events smc_ib_port_event_work
RIP: 0010:__ethtool_get_link_ksettings+0x5c/0x140 net/ethtool/ioctl.c:443
...
Call Trace:
 <TASK>
 ipvlan_ethtool_get_link_ksettings+0x2c/0x40 drivers/net/ipvlan/ipvlan_main.c:411
 __ethtool_get_link_ksettings+0x107/0x140 net/ethtool/ioctl.c:450
 ib_get_eth_speed+0xd2/0x6d0 drivers/infiniband/core/verbs.c:1999
 rxe_query_port+0x14a/0x270 drivers/infiniband/sw/rxe/rxe_verbs.c:62
 __ib_query_port drivers/infiniband/core/device.c:2148 [inline]
 ib_query_port drivers/infiniband/core/device.c:2180 [inline]
 ib_query_port+0x310/0x440 drivers/infiniband/core/device.c:2170
 smc_ib_remember_port_attr net/smc/smc_ib.c:364 [inline]
 smc_ib_port_event_work+0xfa/0x690 net/smc/smc_ib.c:388
...
==================================================================

Execution Flow & Code Context
When backend kernel systems like infiniband (`ib_get_eth_speed`) call `__ethtool_get_link_ksettings()` on a top-level `ipvlan` device to evaluate underlying ethernet capabilities, the execution delegates successfully through the device's mapped proxy routine. However, `ipvlan` triggers a nested fallback lookup to the physical baseline carrier without validating whether the carrier inherently supports ethtool operations:
// drivers/net/ipvlan/ipvlan_main.c
static int ipvlan_ethtool_get_link_ksettings(struct net_device *dev,
					     struct ethtool_link_ksettings *cmd)
{
	const struct ipvl_dev *ipvlan = netdev_priv(dev);

	return __ethtool_get_link_ksettings(ipvlan->phy_dev, cmd); // <-- Nested fallback call onto phy_dev
}
Unfortunately, the exported helper routine `__ethtool_get_link_ksettings()` relies strictly on `dev->ethtool_ops` being a valid populated pointer and makes no assertions defensively prior to calling the callback layout:
// net/ethtool/ioctl.c
int __ethtool_get_link_ksettings(struct net_device *dev,
				 struct ethtool_link_ksettings *link_ksettings)
{
	ASSERT_RTNL();

	if (!dev->ethtool_ops->get_link_ksettings) // <-- NULL pointer dereference (fault at +0x1f8)
		return -EOPNOTSUPP;
	...
}
Root Cause Analysis
The bug constitutes a NULL pointer dereference explicitly triggered within `__ethtool_get_link_ksettings()`. Because the API is exported for transparent kernel-centric consumption (e.g. by `ib_get_eth_speed`), it bypasses the robust validation standard userspace calls experience via the `ethtool_ioctl` ioctl wrapper, completely overlooking empty/NULL `dev->ethtool_ops` arrays. 

When `ipvlan` bridges the request down to an unyielding backend host (`ipvlan->phy_dev`), and the host operates as a virtual loop or dummy lacking any registered `ethtool_ops`, the fetch targets `dev->ethtool_ops->get_link_ksettings`. Based on the API's pointer offset in `include/linux/ethtool.h`, this lands precisely at structural index `0x1F8`, culminating in a fatal supervisor read fault.
Unfortunately, we were unable to generate a reproducer for this bug.

Potential Impact
This memory management gap presents a local kernel panic/Denial of Service (DoS). It manifests silently anytime nested virtual abstractions process asynchronous traffic events requiring network speed capabilities over missing handler arrays, particularly through automated RDMA/IB device initializations.

Proposed Fix
To universally intercept the validation lapse inside the exported generic handler, we suggest introducing a preliminary null-check protecting the interface invocations:
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -440,7 +440,7 @@ int __ethtool_get_link_ksettings(struct net_device *dev,
 {
 	ASSERT_RTNL();
 
-	if (!dev->ethtool_ops->get_link_ksettings)
+	if (!dev->ethtool_ops || !dev->ethtool_ops->get_link_ksettings)
 		return -EOPNOTSUPP;
 
 	if (!netif_device_present(dev))
We would be highly honored if this could be of any help.

Best regards,
RacePilot Team
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help