public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed
@ 2026-03-11 10:03 Jiayuan Chen
  2026-03-12  3:26 ` Jakub Kicinski
  2026-03-16 16:29 ` Leon Romanovsky
  0 siblings, 2 replies; 5+ messages in thread
From: Jiayuan Chen @ 2026-03-11 10:03 UTC (permalink / raw)
  To: linux-rdma, netdev
  Cc: Jiayuan Chen, Jianzhou Zhao, Jiayuan Chen, Jason Gunthorpe,
	Leon Romanovsky, Mark Bloch, Edward Srouji, Or Har-Toov,
	Kalesh AP, Patrisious Haddad, Maher Sanalla, Yishai Hadas,
	Kees Cook, Jang Ingyu, Moni Shoua, Doug Ledford,
	Christian Benvenuti, Selvin Xavier, Yuval Shaia, linux-kernel

From: Jiayuan Chen <jiayuan.chen@shopee.com>

Jianzhou Zhao reported a NULL pointer dereference in
__ethtool_get_link_ksettings [1]. The root cause is a use-after-free
of ipvlan->phy_dev.

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: between
ib_device_get_netdev() and rtnl_lock(), the underlying phy_dev (e.g. a
dummy device) can be unregistered and freed by another thread. When the
ethtool call later recurses through ipvlan_ethtool_get_link_ksettings()
into the freed phy_dev, it dereferences freed memory whose ethtool_ops
reads as NULL, causing the crash at offset 0x1f8.

Fix this by moving ib_device_get_netdev() inside the rtnl_lock() section
so that netdev lookup and the ethtool call are atomic with respect to
device unregistration. Under RTNL, if the phy_dev has been deleted, the
ipvlan device is also unregistered and ib_device_get_netdev() returns NULL
safely.

None of the existing callers of ib_get_eth_speed() hold rtnl_lock, so this
change does not introduce any deadlock.

[1] https://lore.kernel.org/netdev/94089b74-def5-4dd0-9143-1cfbc722fe73@linux.dev/T/#t

Fixes: d41861942fc5 ("IB/core: Add generic function to extract IB speed from netdev")
Reported-by: Jianzhou Zhao <luckd0g@163.com>
Closes: https://lore.kernel.org/netdev/94089b74-def5-4dd0-9143-1cfbc722fe73@linux.dev/T/#t
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
 drivers/infiniband/core/verbs.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

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();
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed
  2026-03-11 10:03 [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed Jiayuan Chen
@ 2026-03-12  3:26 ` Jakub Kicinski
  2026-03-16 16:29 ` Leon Romanovsky
  1 sibling, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2026-03-12  3:26 UTC (permalink / raw)
  To: Jiayuan Chen
  Cc: linux-rdma, netdev, Jiayuan Chen, Jianzhou Zhao, Jason Gunthorpe,
	Leon Romanovsky, Mark Bloch, Edward Srouji, Or Har-Toov,
	Kalesh AP, Patrisious Haddad, Maher Sanalla, Yishai Hadas,
	Kees Cook, Jang Ingyu, Moni Shoua, Doug Ledford,
	Christian Benvenuti, Selvin Xavier, Yuval Shaia, linux-kernel

On Wed, 11 Mar 2026 18:03:08 +0800 Jiayuan Chen wrote:
> Subject: [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed

FWIW this is not a net patch (infiniband is not net)
-- 
pw-bot: nap

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed
  2026-03-11 10:03 [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed Jiayuan Chen
  2026-03-12  3:26 ` Jakub Kicinski
@ 2026-03-16 16:29 ` Leon Romanovsky
  2026-03-17  9:48   ` Jiayuan Chen
  1 sibling, 1 reply; 5+ messages in thread
From: Leon Romanovsky @ 2026-03-16 16:29 UTC (permalink / raw)
  To: Jiayuan Chen
  Cc: linux-rdma, netdev, Jiayuan Chen, Jianzhou Zhao, Jason Gunthorpe,
	Mark Bloch, Edward Srouji, Or Har-Toov, Kalesh AP,
	Patrisious Haddad, Maher Sanalla, Yishai Hadas, Kees Cook,
	Jang Ingyu, Moni Shoua, Doug Ledford, Christian Benvenuti,
	Selvin Xavier, Yuval Shaia, linux-kernel

On Wed, Mar 11, 2026 at 06:03:08PM +0800, Jiayuan Chen wrote:
> From: Jiayuan Chen <jiayuan.chen@shopee.com>
> 
> Jianzhou Zhao reported a NULL pointer dereference in
> __ethtool_get_link_ksettings [1]. The root cause is a use-after-free
> of ipvlan->phy_dev.
> 
> 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: between
> ib_device_get_netdev() and rtnl_lock(), the underlying phy_dev (e.g. a
> dummy device) can be unregistered and freed by another thread.

If ib_device_get_netdev() worked as it was supposed to work, it can't.
That function grabs reference on netdev and returns or netdev with elevated
reference counter which can't be freed or returns NULL.

Thanks

> When the ethtool call later recurses through ipvlan_ethtool_get_link_ksettings()
> into the freed phy_dev, it dereferences freed memory whose ethtool_ops
> reads as NULL, causing the crash at offset 0x1f8.
> 
> Fix this by moving ib_device_get_netdev() inside the rtnl_lock() section
> so that netdev lookup and the ethtool call are atomic with respect to
> device unregistration. Under RTNL, if the phy_dev has been deleted, the
> ipvlan device is also unregistered and ib_device_get_netdev() returns NULL
> safely.
> 
> None of the existing callers of ib_get_eth_speed() hold rtnl_lock, so this
> change does not introduce any deadlock.
> 
> [1] https://lore.kernel.org/netdev/94089b74-def5-4dd0-9143-1cfbc722fe73@linux.dev/T/#t
> 
> Fixes: d41861942fc5 ("IB/core: Add generic function to extract IB speed from netdev")
> Reported-by: Jianzhou Zhao <luckd0g@163.com>
> Closes: https://lore.kernel.org/netdev/94089b74-def5-4dd0-9143-1cfbc722fe73@linux.dev/T/#t
> Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
> ---
>  drivers/infiniband/core/verbs.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> 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();
>  
> -- 
> 2.43.0
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed
  2026-03-16 16:29 ` Leon Romanovsky
@ 2026-03-17  9:48   ` Jiayuan Chen
  2026-03-17 13:41     ` Leon Romanovsky
  0 siblings, 1 reply; 5+ messages in thread
From: Jiayuan Chen @ 2026-03-17  9:48 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: linux-rdma, netdev, Jiayuan Chen, Jianzhou Zhao, Jason Gunthorpe,
	Mark Bloch, Edward Srouji, Or Har-Toov, Kalesh AP,
	Patrisious Haddad, Maher Sanalla, Yishai Hadas, Kees Cook,
	Jang Ingyu, Moni Shoua, Doug Ledford, Christian Benvenuti,
	Selvin Xavier, Yuval Shaia, linux-kernel


On 3/17/26 12:29 AM, Leon Romanovsky wrote:
> On Wed, Mar 11, 2026 at 06:03:08PM +0800, Jiayuan Chen wrote:
>> From: Jiayuan Chen <jiayuan.chen@shopee.com>
>>
>> Jianzhou Zhao reported a NULL pointer dereference in
>> __ethtool_get_link_ksettings [1]. The root cause is a use-after-free
>> of ipvlan->phy_dev.
>>
>> 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: between
>> ib_device_get_netdev() and rtnl_lock(), the underlying phy_dev (e.g. a
>> dummy device) can be unregistered and freed by another thread.
> If ib_device_get_netdev() worked as it was supposed to work, it can't.
> That function grabs reference on netdev and returns or netdev with elevated
> reference counter which can't be freed or returns NULL.
>
> Thanks
>

ipvlan's phy_dev is safe in the data path — TX/RX runs in softirq
context with RCU protection, no lock needed per packet.

The issue here is in the control path. __ethtool_get_link_ksettings()
requires rtnl_lock() — all existing ethtool callers follow this:

- ioctl path: rtnl_lock() is taken first, then __dev_get_by_name()
looks up the dev without even holding a refcnt — relying entirely
on RTNL for safety. (net/ethtool/ioctl.c:3571, 3249)
- netlink path: dev is looked up with refcnt first, but the actual
ethtool ops run under rtnl_lock(). (net/ethtool/netlink.c:527-533)

Under RTNL, phy_dev cannot disappear because phy_dev unregistration
triggers NETDEV_UNREGISTER which deletes ipvlan first — all within
the same RTNL context. That's why no virtual netdev driver (ipvlan,
macvlan, bond, etc.) holds an extra refcnt on the lower dev in its
ethtool callbacks.

ib_get_eth_speed() calls __ethtool_get_link_ksettings() under
rtnl_lock(), but obtains the netdev before it. Moving the lookup
inside rtnl_lock() makes the netdev resolution and ethtool call
atomic w.r.t. device unregistration, consistent with how ethtool's
own paths work.


Thanks


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed
  2026-03-17  9:48   ` Jiayuan Chen
@ 2026-03-17 13:41     ` Leon Romanovsky
  0 siblings, 0 replies; 5+ messages in thread
From: Leon Romanovsky @ 2026-03-17 13:41 UTC (permalink / raw)
  To: Jiayuan Chen
  Cc: linux-rdma, netdev, Jiayuan Chen, Jianzhou Zhao, Jason Gunthorpe,
	Mark Bloch, Edward Srouji, Or Har-Toov, Kalesh AP,
	Patrisious Haddad, Maher Sanalla, Yishai Hadas, Kees Cook,
	Jang Ingyu, Moni Shoua, Doug Ledford, Christian Benvenuti,
	Selvin Xavier, Yuval Shaia, linux-kernel

On Tue, Mar 17, 2026 at 05:48:55PM +0800, Jiayuan Chen wrote:
> 
> On 3/17/26 12:29 AM, Leon Romanovsky wrote:
> > On Wed, Mar 11, 2026 at 06:03:08PM +0800, Jiayuan Chen wrote:
> > > From: Jiayuan Chen <jiayuan.chen@shopee.com>
> > > 
> > > Jianzhou Zhao reported a NULL pointer dereference in
> > > __ethtool_get_link_ksettings [1]. The root cause is a use-after-free
> > > of ipvlan->phy_dev.
> > > 
> > > 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: between
> > > ib_device_get_netdev() and rtnl_lock(), the underlying phy_dev (e.g. a
> > > dummy device) can be unregistered and freed by another thread.
> > If ib_device_get_netdev() worked as it was supposed to work, it can't.
> > That function grabs reference on netdev and returns or netdev with elevated
> > reference counter which can't be freed or returns NULL.
> > 
> > Thanks
> > 
> 
> ipvlan's phy_dev is safe in the data path — TX/RX runs in softirq
> context with RCU protection, no lock needed per packet.
> 
> The issue here is in the control path. __ethtool_get_link_ksettings()
> requires rtnl_lock() — all existing ethtool callers follow this:
> 
> - ioctl path: rtnl_lock() is taken first, then __dev_get_by_name()
> looks up the dev without even holding a refcnt — relying entirely
> on RTNL for safety. (net/ethtool/ioctl.c:3571, 3249)
> - netlink path: dev is looked up with refcnt first, but the actual
> ethtool ops run under rtnl_lock(). (net/ethtool/netlink.c:527-533)
> 
> Under RTNL, phy_dev cannot disappear because phy_dev unregistration
> triggers NETDEV_UNREGISTER which deletes ipvlan first — all within
> the same RTNL context. That's why no virtual netdev driver (ipvlan,
> macvlan, bond, etc.) holds an extra refcnt on the lower dev in its
> ethtool callbacks.
> 
> ib_get_eth_speed() calls __ethtool_get_link_ksettings() under
> rtnl_lock(), but obtains the netdev before it. Moving the lookup
> inside rtnl_lock() makes the netdev resolution and ethtool call
> atomic w.r.t. device unregistration, consistent with how ethtool's
> own paths work.

Please reread my earlier response and explain how an ipvlan device can
disappear immediately after a successful call to ib_device_get_netdev().

Thanks

> 
> 
> Thanks
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-03-17 13:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 10:03 [PATCH net v1] IB/core: Fix use-after-free of ipvlan phy_dev in ib_get_eth_speed Jiayuan Chen
2026-03-12  3:26 ` Jakub Kicinski
2026-03-16 16:29 ` Leon Romanovsky
2026-03-17  9:48   ` Jiayuan Chen
2026-03-17 13:41     ` Leon Romanovsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox