From: Eric Dumazet <edumazet@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>
Subject: [PATCH net 2/4] drop_monitor: use timer_shutdown_sync() to prevent timer rearming during teardown
Date: Thu, 10 Sep 2026 20:46:10 +0000 [thread overview]
Message-ID: <20260910204612.3762015-3-edumazet@google.com> (raw)
In-Reply-To: <20260910204612.3762015-1-edumazet@google.com>
In drop_monitor teardown paths (net_dm_trace_off_set(),
net_dm_hw_monitor_stop(), and error unwind paths in net_dm_trace_on_set()
and net_dm_hw_monitor_start()), per-CPU timers are stopped using
timer_delete_sync() followed by cancel_work_sync().
However, there is a circular dependency between send_timer and
dm_alert_work:
1) sched_send_work() (timer callback) schedules dm_alert_work.
2) send_dm_alert() / net_dm_hw_summary_work() calls reset_per_cpu_data()
or net_dm_hw_reset_per_cpu_data().
3) If memory allocation fails under memory pressure in the reset
function, it re-arms the timer via mod_timer(&data->send_timer, ...).
If dm_alert_work is running concurrently while timer_delete_sync()
executes on another CPU, an allocation failure in the worker will
re-arm the timer after timer_delete_sync() has already returned.
Once cancel_work_sync() completes and module_put() is called, the timer
remains active in the timer wheel. If the module is then unloaded, the
timer will fire and execute sched_send_work() in freed memory,
triggering a kernel panic / use-after-free.
Switch from timer_delete_sync() to timer_shutdown_sync(). This guarantees
that any in-flight timer handler has finished and prevents subsequent
re-arming attempts from running workers from succeeding. When monitoring
is restarted later, timer_setup() is invoked, which cleanly
re-initializes the timer.
Fixes: 9398e9c0b1d4 ("drop_monitor: Perform cleanup upon probe registration failure")
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/core/drop_monitor.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 018d19e3a71de0be50bcc5753ba65f715f678aaa..873155ca72432924322bb7961996dd3430d052bc 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -1083,7 +1083,7 @@ static int net_dm_hw_monitor_start(struct netlink_ext_ack *extack)
struct per_cpu_dm_data *hw_data = &per_cpu(dm_hw_cpu_data, cpu);
struct sk_buff *skb;
- timer_delete_sync(&hw_data->send_timer);
+ timer_shutdown_sync(&hw_data->send_timer);
cancel_work_sync(&hw_data->dm_alert_work);
while ((skb = __skb_dequeue(&hw_data->drop_queue))) {
struct devlink_trap_metadata *hw_metadata;
@@ -1117,7 +1117,7 @@ static void net_dm_hw_monitor_stop(struct netlink_ext_ack *extack)
struct per_cpu_dm_data *hw_data = &per_cpu(dm_hw_cpu_data, cpu);
struct sk_buff *skb;
- timer_delete_sync(&hw_data->send_timer);
+ timer_shutdown_sync(&hw_data->send_timer);
cancel_work_sync(&hw_data->dm_alert_work);
while ((skb = __skb_dequeue(&hw_data->drop_queue))) {
struct devlink_trap_metadata *hw_metadata;
@@ -1179,7 +1179,7 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack)
struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu);
struct sk_buff *skb;
- timer_delete_sync(&data->send_timer);
+ timer_shutdown_sync(&data->send_timer);
cancel_work_sync(&data->dm_alert_work);
while ((skb = __skb_dequeue(&data->drop_queue)))
consume_skb(skb);
@@ -1207,7 +1207,7 @@ static void net_dm_trace_off_set(void)
struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu);
struct sk_buff *skb;
- timer_delete_sync(&data->send_timer);
+ timer_shutdown_sync(&data->send_timer);
cancel_work_sync(&data->dm_alert_work);
while ((skb = __skb_dequeue(&data->drop_queue)))
consume_skb(skb);
--
2.55.0.1007.g17ff1f9808-goog
next prev parent reply other threads:[~2026-09-10 20:46 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 20:46 [PATCH net 0/4] net: drop_monitor: fix concurrency issues, preemption warning, and buffer overrun Eric Dumazet
2026-09-10 20:46 ` [PATCH net 1/4] drop_monitor: synchronize tracepoint unregistration on error path Eric Dumazet
2026-09-11 9:46 ` Hangbin Liu
2026-09-10 20:46 ` Eric Dumazet [this message]
2026-09-11 9:57 ` [PATCH net 2/4] drop_monitor: use timer_shutdown_sync() to prevent timer rearming during teardown Hangbin Liu
2026-09-10 20:46 ` [PATCH net 3/4] drop_monitor: use raw_cpu_ptr() in tracepoint probes Eric Dumazet
2026-09-10 20:46 ` [PATCH net 4/4] drop_monitor: fix out-of-bounds write in reset_per_cpu_data() Eric Dumazet
2026-09-11 10:02 ` Hangbin Liu
2026-09-11 21:08 ` netdev-bot+sashiko
2026-09-12 14:46 ` Eric Dumazet
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=20260910204612.3762015-3-edumazet@google.com \
--to=edumazet@google.com \
--cc=davem@davemloft.net \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--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