All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: Jianzhou Zhao <luckd0g@163.com>,
	edumazet@google.com, davem@davemloft.net, andrew+netdev@lunn.ch,
	kuba@kernel.org, pabeni@redhat.com, sdf@fomichev.me,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: BUG: unable to handle kernel NULL pointer dereference in __ethtool_get_link_ksettings
Date: Wed, 11 Mar 2026 17:13:12 +0800	[thread overview]
Message-ID: <94089b74-def5-4dd0-9143-1cfbc722fe73@linux.dev> (raw)
In-Reply-To: <a3fb1f.6f59.19cdbf3d67d.Coremail.luckd0g@163.com>


On 3/11/26 4:11 PM, Jianzhou Zhao wrote:
>
> 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:
> ```c
> // 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:
> ```c
> // 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:
>
> ```diff
> --- 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


Thanks for the report.

The root cause is a use-after-free of ipvlan->phy_dev, not a simple missing
NULL check on ethtool_ops.

In ib_get_eth_speed(), ib_device_get_netdev() obtains a reference to the
ipvlan device *outside* of rtnl_lock(). This creates a race window where
the underlying phy_dev can be unregistered and freed before rtnl_lock() 
is acquired.

Then recurses through ipvlan_ethtool_get_link_ksettings()
into phy_dev, it dereferences freed memory — which happens to read as 
NULL for
ethtool_ops, causing the crash at offset 0x1f8.

Diff below:

diff --git a/drivers/infiniband/core/verbs.c 
b/drivers/infiniband/core/verbs.c
index 575b4a4b200b..f16d11e7c2e3 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -2046,11 +2046,13 @@ int ib_get_eth_speed(struct ib_device *dev, u32 
port_num, u16 *speed, u8 *width)
         if (rdma_port_get_link_layer(dev, port_num) != 
IB_LINK_LAYER_ETHERNET)
                 return -EINVAL;

+       rtnl_lock();
         netdev = ib_device_get_netdev(dev, port_num);
-       if (!netdev)
+       if (!netdev) {
+               rtnl_unlock();
                 return -ENODEV;
+       }

-       rtnl_lock();
         rc = __ethtool_get_link_ksettings(netdev, &lksettings);
         rtnl_unlock();


      reply	other threads:[~2026-03-11  9:13 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-11  8:11 BUG: unable to handle kernel NULL pointer dereference in __ethtool_get_link_ksettings Jianzhou Zhao
2026-03-11  9:13 ` Jiayuan Chen [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=94089b74-def5-4dd0-9143-1cfbc722fe73@linux.dev \
    --to=jiayuan.chen@linux.dev \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luckd0g@163.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sdf@fomichev.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.