* [PATCH net] sfc: fix use-after-free of filter_work in efx_realloc_channels()
@ 2026-10-22 13:39 Sicong Huang
2026-10-22 13:47 ` netdev-bot+sinfo
2026-10-22 14:36 ` Edward Cree
0 siblings, 2 replies; 3+ messages in thread
From: Sicong Huang @ 2026-10-22 13:39 UTC (permalink / raw)
To: netdev
Cc: Edward Cree, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Kees Cook, linux-net-drivers,
linux-kernel, Sicong Huang
With CONFIG_RFS_ACCEL, each channel has a delayed work item,
channel->filter_work, that expires aRFS filters. efx_poll() queues it
with mod_delayed_work(), and efx_filter_rfs_expire() always re-arms it
with schedule_delayed_work(dwork, 30 * HZ). Once efx_poll() has queued
it, the work is therefore always pending, queued or running. It is
only cancelled in efx_remove_filters(), which is not called on the ring
resize path.
Resizing the rings via ethtool -G calls efx_realloc_channels(). It
copies each channel, swaps the copies into efx->channel[] and frees the
old channel structures. Nothing on this path cancels the old channel's
filter_work. So the old filter_work can fire after its channel has
been freed. The timer core and delayed_work_timer_fn() then access
the freed delayed_work. efx_filter_rfs_expire() gets the freed channel
back via container_of(), dereferences it and re-arms the timer inside
the freed object.
A possible race is:
CPU0 CPU1
efx_ethtool_set_ringparam()
efx_realloc_channels()
efx_stop_all() //NAPI stopped, timer still armed
efx_copy_channel()
swap(efx->channel[i], ...)
efx_remove_channel(old)
kfree(old) //free here!
old->filter_work.timer fires
delayed_work_timer_fn()
efx_filter_rfs_expire()
channel = container_of(dwork, ...)
channel->rfs_last_expiry //UAF!
schedule_delayed_work(dwork, 30 * HZ)
Because the work re-arms itself every 30 seconds, this is not a narrow
timing window. One successful ethtool -G after efx_poll() has queued
filter_work is enough to trigger it.
The Siena driver has its own copy of this code in
efx_siena_realloc_channels() and has the same problem.
Fix this in both drivers by calling cancel_delayed_work_sync() on
filter_work before freeing an unused channel. The work does not take
the RTNL. It only trylocks efx->rps_mutex, and the filter table locks
it takes are never held while waiting for the RTNL, so waiting for it
under the RTNL cannot deadlock. On the copy failure and rollback paths,
the freed channels are new copies whose filter_work was never queued,
so the cancel does nothing there.
Signed-off-by: Sicong Huang <congei42@163.com>
---
drivers/net/ethernet/sfc/efx_channels.c | 3 +++
drivers/net/ethernet/sfc/siena/efx_channels.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c
index f4dc3f3f4416..3773a70e1e7d 100644
--- a/drivers/net/ethernet/sfc/efx_channels.c
+++ b/drivers/net/ethernet/sfc/efx_channels.c
@@ -896,6 +896,9 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
for (i = 0; i < efx->n_channels; i++) {
channel = other_channel[i];
if (channel && channel->type->copy) {
+#ifdef CONFIG_RFS_ACCEL
+ cancel_delayed_work_sync(&channel->filter_work);
+#endif
efx_fini_napi_channel(channel);
efx_remove_channel(channel);
kfree(channel);
diff --git a/drivers/net/ethernet/sfc/siena/efx_channels.c b/drivers/net/ethernet/sfc/siena/efx_channels.c
index 1fc343598771..d20144f1679a 100644
--- a/drivers/net/ethernet/sfc/siena/efx_channels.c
+++ b/drivers/net/ethernet/sfc/siena/efx_channels.c
@@ -930,6 +930,9 @@ int efx_siena_realloc_channels(struct efx_nic *efx, u32 rxq_entries,
for (i = 0; i < efx->n_channels; i++) {
channel = other_channel[i];
if (channel && channel->type->copy) {
+#ifdef CONFIG_RFS_ACCEL
+ cancel_delayed_work_sync(&channel->filter_work);
+#endif
efx_fini_napi_channel(channel);
efx_siena_remove_channel(channel);
kfree(channel);
base-commit: f4377bf85887f57b59abb5479f7660a81ffe4449
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] sfc: fix use-after-free of filter_work in efx_realloc_channels()
2026-10-22 13:39 [PATCH net] sfc: fix use-after-free of filter_work in efx_realloc_channels() Sicong Huang
@ 2026-10-22 13:47 ` netdev-bot+sinfo
2026-10-22 14:36 ` Edward Cree
1 sibling, 0 replies; 3+ messages in thread
From: netdev-bot+sinfo @ 2026-10-22 13:47 UTC (permalink / raw)
To: Sicong Huang
Cc: netdev, Edward Cree, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Kees Cook, linux-net-drivers,
linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
- What hardware the change was tested on. For driver fixes please
mention the device (and if relevant firmware version) used for
testing, or say that the change was not tested on real hardware.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] sfc: fix use-after-free of filter_work in efx_realloc_channels()
2026-10-22 13:39 [PATCH net] sfc: fix use-after-free of filter_work in efx_realloc_channels() Sicong Huang
2026-10-22 13:47 ` netdev-bot+sinfo
@ 2026-10-22 14:36 ` Edward Cree
1 sibling, 0 replies; 3+ messages in thread
From: Edward Cree @ 2026-10-22 14:36 UTC (permalink / raw)
To: Sicong Huang, netdev
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Kees Cook, linux-net-drivers, linux-kernel
On 22/10/2026 14:39, Sicong Huang wrote:
> With CONFIG_RFS_ACCEL, each channel has a delayed work item,
> channel->filter_work, that expires aRFS filters. efx_poll() queues it
> with mod_delayed_work(), and efx_filter_rfs_expire() always re-arms it
> with schedule_delayed_work(dwork, 30 * HZ). Once efx_poll() has queued
> it, the work is therefore always pending, queued or running. It is
> only cancelled in efx_remove_filters(), which is not called on the ring
> resize path.
...
> Fix this in both drivers by calling cancel_delayed_work_sync() on
> filter_work before freeing an unused channel. The work does not take
> the RTNL. It only trylocks efx->rps_mutex, and the filter table locks
> it takes are never held while waiting for the RTNL, so waiting for it
> under the RTNL cannot deadlock. On the copy failure and rollback paths,
> the freed channels are new copies whose filter_work was never queued,
> so the cancel does nothing there.
>
> Signed-off-by: Sicong Huang <congei42@163.com>
The analysis looks correct, but I wonder if rather than placing the
cancel_delayed_work_sync() inline in efx_realloc_channels(), it should
be done by efx_remove_channel() (or rolled up with the kfree() into a
new efx_free_channel(), since it's undoing efx_alloc_channel() rather
than efx_probe_channel()), to reduce the risk of the same race popping
up elsewhere. Consumers of the channels API should not need to know
that they have to do this 'magic' cancel to safely free a channel,
that's a layering violation.
(Actually, it's a layering violation that filter_work even lives in the
efx_channel and not its efx_rx_queue, but I never had time to fix that
and am now not likely to — I commend the idea to future maintainers.)
-ed
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-22 14:36 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22 13:39 [PATCH net] sfc: fix use-after-free of filter_work in efx_realloc_channels() Sicong Huang
2026-10-22 13:47 ` netdev-bot+sinfo
2026-10-22 14:36 ` Edward Cree
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®