From: Sicong Huang <congei42@163.com>
To: netdev@vger.kernel.org
Cc: Jakub Kicinski <kuba@kernel.org>, Simon Horman <horms@kernel.org>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Louis Peens <louis.peens@corigine.com>,
Hui Zhou <hui.zhou@corigine.com>,
oss-drivers@corigine.com, linux-kernel@vger.kernel.org,
Sicong Huang <congei42@163.com>
Subject: [PATCH net] nfp: flower: fix use-after-free in neighbour update work
Date: Sat, 24 Oct 2026 12:49:03 +0800 [thread overview]
Message-ID: <20261024044903.1130380-1-congei42@163.com> (raw)
The netevent notifier handles neighbour updates and redirects by
queuing nfp_tun_neigh_update() on system_highpri_wq. Each work item
holds a reference to the neighbour, but only stores a pointer to the
flower app.
During device removal, nfp_tunnel_config_stop() unregisters the
notifier. This waits for notifier callbacks to return, but does not
wait for the work they queued. The teardown then frees app->priv and
app without waiting for these work items. Flushing cmsg_work in
nfp_flower_clean() does not cover the neighbour update work.
A pending work item can therefore run after the app has been freed.
Its call to nfp_flower_get_port_id_from_netdev() can then access freed
memory while checking whether the neighbour's device can be offloaded.
Even notifications for unrelated devices can reach this check. The
same problem affects shutdown and probe error paths that tear down the
app after the netevent notifier has been registered.
One possible interleaving is shown below. The neighbour belongs to
another network device that remains registered.
CPU0 (remove) CPU1 (notifier / kworker)
nfp_tun_neigh_event_handler()
queue_work(system_highpri_wq, ...)
return
/* Work has not run yet. */
nfp_tunnel_config_stop()
unregister_netevent_notifier()
/* Notifier callbacks have finished, but work may be pending. */
nfp_flower_clean()
vfree(app->priv)
app->priv = NULL
nfp_app_free()
kfree(app)
nfp_tun_neigh_update()
app = update_work->app
nfp_flower_get_port_id_from_netdev()
app->priv /* use-after-free */
The work items are allocated per event and free themselves, so they
cannot be cancelled individually, and flushing system_highpri_wq is
not allowed. Use a dedicated workqueue for neighbour updates instead.
In nfp_tunnel_config_stop(), unregister the notifier and destroy the
workqueue before cleaning up the tunnel state. This prevents new work
from being queued and waits for pending and running work to finish
while the app and its resources are still valid.
Found by code inspection.
Fixes: 0ad722bd9ee3 ("nfp: flower: fix for take a mutex lock in soft irq context and rcu lock")
Signed-off-by: Sicong Huang <congei42@163.com>
---
.../net/ethernet/netronome/nfp/flower/main.h | 2 ++
.../netronome/nfp/flower/tunnel_conf.c | 24 ++++++++++++++-----
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h
index 2b7c947ff4f2..bd4399758ed4 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/main.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/main.h
@@ -94,6 +94,7 @@ struct nfp_fl_stats_id {
* @ipv6_off_lock: Lock for the IPv6 address list
* @mac_off_ids: IDA to manage id assignment for offloaded MACs
* @neigh_nb: Notifier to monitor neighbour state
+ * @neigh_wq: Workqueue for neighbour updates
*/
struct nfp_fl_tunnel_offloads {
struct rhashtable offloaded_macs;
@@ -103,6 +104,7 @@ struct nfp_fl_tunnel_offloads {
struct mutex ipv6_off_lock;
struct ida mac_off_ids;
struct notifier_block neigh_nb;
+ struct workqueue_struct *neigh_wq;
};
/**
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 3b47e9fe64e1..46b6cda7f3d3 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -736,7 +736,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
if (!update_work)
return NOTIFY_DONE;
- queue_work(system_highpri_wq, &update_work->work);
+ queue_work(app_priv->tun.neigh_wq, &update_work->work);
return NOTIFY_DONE;
}
@@ -1509,6 +1509,13 @@ int nfp_tunnel_config_start(struct nfp_app *app)
if (err)
return err;
+ priv->tun.neigh_wq = alloc_workqueue("nfp-flower-neigh",
+ WQ_HIGHPRI | WQ_PERCPU, 0);
+ if (!priv->tun.neigh_wq) {
+ err = -ENOMEM;
+ goto err_free_macs;
+ }
+
ida_init(&priv->tun.mac_off_ids);
/* Initialise priv data for IPv4/v6 offloading. */
@@ -1521,13 +1528,17 @@ int nfp_tunnel_config_start(struct nfp_app *app)
priv->tun.neigh_nb.notifier_call = nfp_tun_neigh_event_handler;
err = register_netevent_notifier(&priv->tun.neigh_nb);
- if (err) {
- rhashtable_free_and_destroy(&priv->tun.offloaded_macs,
- nfp_check_rhashtable_empty, NULL);
- return err;
- }
+ if (err)
+ goto err_destroy_neigh_wq;
return 0;
+
+err_destroy_neigh_wq:
+ destroy_workqueue(priv->tun.neigh_wq);
+err_free_macs:
+ rhashtable_free_and_destroy(&priv->tun.offloaded_macs,
+ nfp_check_rhashtable_empty, NULL);
+ return err;
}
void nfp_tunnel_config_stop(struct nfp_app *app)
@@ -1537,6 +1548,7 @@ void nfp_tunnel_config_stop(struct nfp_app *app)
struct list_head *ptr, *storage;
unregister_netevent_notifier(&priv->tun.neigh_nb);
+ destroy_workqueue(priv->tun.neigh_wq);
ida_destroy(&priv->tun.mac_off_ids);
base-commit: 7076f684d5132e6a6145e1da2fa74771ecd052e5
--
2.34.1
next reply other threads:[~2026-10-24 4:49 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 4:49 Sicong Huang [this message]
2026-10-24 4:55 ` netdev-bot+sinfo
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=20261024044903.1130380-1-congei42@163.com \
--to=congei42@163.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=hui.zhou@corigine.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=louis.peens@corigine.com \
--cc=netdev@vger.kernel.org \
--cc=oss-drivers@corigine.com \
--cc=pabeni@redhat.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
all inboxes | Powered by JetHome®