syzbot.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Krystian Kaniewski <krystianmkaniewski@gmail.com>
To: syzbot <syzbot@kernel.org>,
	syzkaller-upstream-moderation@googlegroups.com
Cc: syzbot@lists.linux.dev
Subject: Re: [PATCH RFC v3] ipvlan: keep lower device alive until private destruction
Date: Tue, 28 Jul 2026 10:36:10 +0200	[thread overview]
Message-ID: <00a5b5be-74c3-4666-90e5-b331d3090272@gmail.com> (raw)
In-Reply-To: <07edf3e0-84dd-47b0-8203-e0b8f3b9d5b5@mail.kernel.org>

#syz upstream

On 7/19/2026 2:49 PM, syzbot wrote:
> Commit 40b9d1ab63f5 ("ipvlan: hold lower dev to avoid possible
> use-after-free") added a reference to the lower net_device owned by struct
> ipvl_port. However, this reference is released when the last
> ipvlan_uninit() reduces port->count to zero and calls
> ipvlan_port_destroy(), which can happen before all outstanding external
> references to the ipvlan netdev have drained.
>
> Specifically, RXE acts as an asynchronous owner in this scenario. RXE
> queues RDMA device removal on NETDEV_UNREGISTER, meaning it can retain a
> reference to the ipvlan netdev after ndo_uninit has completed. This allows
> a later SMC port query to reach the ipvlan device and access its phy_dev.
>
> This leads to the following sequence:
> 1. The shared ipvl_port owns the reference to the lower net_device
> (phy_dev).
> 2. The last ipvlan_uninit() drops this reference by calling
> ipvlan_port_destroy() when port->count reaches zero.
> 3. RXE retains a reference to the ipvlan netdev, keeping it alive.
> 4. The lower net_device's refcount drops to 1 and it is freed by
> netdev_run_todo(), leaving ipvlan->phy_dev as a dangling pointer. A
> subsequent SMC port query accesses this dangling pointer, triggering a
> use-after-free.
> 5. A new per-device hold keeps phy_dev alive until ipvlan_dev_free() runs.
>
> The KASAN report illustrates this use-after-free:
>
> BUG: KASAN: slab-use-after-free in netdev_need_ops_lock
> include/net/netdev_lock.h:30 [inline]
> BUG: KASAN: slab-use-after-free in netdev_lock_ops
> include/net/netdev_lock.h:41 [inline]
> BUG: KASAN: slab-use-after-free in __ethtool_get_link_ksettings+0x230/0x250
> net/ethtool/ioctl.c:463
> Read of size 1 at addr ffff8881988dae09 by task kworker/1:3/1289
>
> Call Trace:
>   <TASK>
>    __ethtool_get_link_ksettings+0x230/0x250 net/ethtool/ioctl.c:463
>    __ethtool_get_link_ksettings+0x11f/0x250 net/ethtool/ioctl.c:464
>    ib_get_eth_speed+0x180/0x7f0 drivers/infiniband/core/verbs.c:2052
>    rxe_query_port+0x93/0x3d0 drivers/infiniband/sw/rxe/rxe_verbs.c:56
>    __ib_query_port drivers/infiniband/core/device.c:2129 [inline]
>    ib_query_port+0x16e/0x830 drivers/infiniband/core/device.c:2161
>    smc_ib_remember_port_attr net/smc/smc_ib.c:364 [inline]
>    smc_ib_port_event_work+0x147/0x920 net/smc/smc_ib.c:388
>   </TASK>
>
> Fix this by holding a reference to the lower net_device using a
> netdevice_tracker in struct ipvl_dev. The reference is acquired in
> ipvlan_init() and released in the priv_destructor callback
> (ipvlan_dev_free()). Releasing the reference in ipvlan_dev_free()
> guarantees that the lower net_device is held until outstanding external
> references to the ipvlan netdev have drained and before final private
> teardown and object release. This mirrors the behavior of other stacked
> devices like macvlan and vlan, and safely covers ipvtap devices as well.
>
> Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
> Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
> Reported-by: syzbot+5fe14f2ff4ccbace9a26@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=5fe14f2ff4ccbace9a26
> Link: https://syzkaller.appspot.com/ai_job?id=3e3edd19-4e52-49d3-bfdb-ebdde1bda5c3
> To: "Andrew Lunn" <andrew+netdev@lunn.ch>
> To: "David S. Miller" <davem@davemloft.net>
> To: "Eric Dumazet" <edumazet@google.com>
> To: "Jakub Kicinski" <kuba@kernel.org>
> To: <netdev@vger.kernel.org>
> To: "Paolo Abeni" <pabeni@redhat.com>
> Cc: "Dmitry Skorodumov" <dskr99@gmail.com>
> Cc: "Kees Cook" <kees@kernel.org>
> Cc: <linux-kernel@vger.kernel.org>
>
> ---
> v3:
> - Updated the commit description to correct the explanation of the lower-device reference release and the role of RXE.
>
> v2:
> - Updated the patch subject to "ipvlan: keep lower device alive until private destruction"
> - Rewrote the commit message to clarify that commit 40b9d1ab63f5 added a lower-device reference owned by struct ipvl_port
> - Described the lower device generically as a lower net_device
> - Replaced the full KASAN report with only the relevant call chain
> - Corrected the description of priv_destructor
> https://lore.kernel.org/all/7d8162e1-a546-40b8-b9ea-7c0e164ef8e8@mail.kernel.org/T/
>
> v1:
> https://lore.kernel.org/all/e66f374b-905f-471b-989e-60a3e0505873@mail.kernel.org/T/
> ---
> diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
> index 80f84fc87..13cdad002 100644
> --- a/drivers/net/ipvlan/ipvlan.h
> +++ b/drivers/net/ipvlan/ipvlan.h
> @@ -64,6 +64,7 @@ struct ipvl_dev {
>   	struct list_head	pnode;
>   	struct ipvl_port	*port;
>   	struct net_device	*phy_dev;
> +	netdevice_tracker dev_tracker;
>   	struct list_head	addrs;
>   	struct ipvl_pcpu_stats	__percpu *pcpu_stats;
>   	DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE);
> diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
> index ed46439a9..b1435296a 100644
> --- a/drivers/net/ipvlan/ipvlan_main.c
> +++ b/drivers/net/ipvlan/ipvlan_main.c
> @@ -162,6 +162,9 @@ static int ipvlan_init(struct net_device *dev)
>   	}
>   	port = ipvlan_port_get_rtnl(phy_dev);
>   	port->count += 1;
> +
> +	netdev_hold(phy_dev, &ipvlan->dev_tracker, GFP_KERNEL);
> +
>   	return 0;
>   }
>   
> @@ -673,6 +676,13 @@ void ipvlan_link_delete(struct net_device *dev, struct list_head *head)
>   }
>   EXPORT_SYMBOL_GPL(ipvlan_link_delete);
>   
> +static void ipvlan_dev_free(struct net_device *dev)
> +{
> +	struct ipvl_dev *ipvlan = netdev_priv(dev);
> +
> +	netdev_put(ipvlan->phy_dev, &ipvlan->dev_tracker);
> +}
> +
>   void ipvlan_link_setup(struct net_device *dev)
>   {
>   	ether_setup(dev);
> @@ -682,6 +692,7 @@ void ipvlan_link_setup(struct net_device *dev)
>   	dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
>   	dev->netdev_ops = &ipvlan_netdev_ops;
>   	dev->needs_free_netdev = true;
> +	dev->priv_destructor = ipvlan_dev_free;
>   	dev->header_ops = &ipvlan_header_ops;
>   	dev->ethtool_ops = &ipvlan_ethtool_ops;
>   }
>
>
> base-commit: 8cdeaa50eae8dad34885515f62559ee83e7e8dda

      reply	other threads:[~2026-07-28  8:36 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-19 12:49 [PATCH RFC v3] ipvlan: keep lower device alive until private destruction syzbot
2026-07-28  8:36 ` Krystian Kaniewski [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=00a5b5be-74c3-4666-90e5-b331d3090272@gmail.com \
    --to=krystianmkaniewski@gmail.com \
    --cc=syzbot@kernel.org \
    --cc=syzbot@lists.linux.dev \
    --cc=syzkaller-upstream-moderation@googlegroups.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).