[PATCH 08/24] serial: 8250: cancel overrun backoff work on port shutdown and unregister
From: Greg Kroah-Hartman
Date: Tue Oct 27 2026 - 07:11:21 EST
From: Joshua Rogers <linux@xxxxxxxxx>
The overrun_backoff delayed work can be scheduled from IRQ handlers in
8250_fsl.c and 8250_omap.c via schedule_delayed_work(). However, this
work is never canceled in the shutdown or unregister paths, so it can
fire after the port has been torn down, causing stale hardware access or
use-after-free.
The existing synchronize_irq() calls in the shutdown path only
synchronize with the IRQ handler itself, not with workqueue callbacks
that the handler has already enqueued. Add cancel_delayed_work_sync()
after the IRQ is quiesced in serial8250_do_shutdown() (the generic
shutdown path used by FSL and others), omap_8250_shutdown() (the
OMAP-specific shutdown path), and serial8250_unregister_port() (the
module unload / hot-unplug path).
Cc: Jiri Slaby <jirislaby@xxxxxxxxxx>
Cc: John Ogness <john.ogness@xxxxxxxxxxxxx>
Cc: Joshua Rogers <linux@xxxxxxxxx>
Cc: Fushuai Wang <wangfushuai@xxxxxxxxx>
Cc: Crescent Hsieh <crescentcy.hsieh@xxxxxxxx>
Cc: "Uwe Kleine-König (The Capable Hub)" <u.kleine-koenig@xxxxxxxxxxxx>
Cc: Moteen Shah <m-shah@xxxxxx>
Cc: Kendall Willis <k-willis@xxxxxx>
Cc: Frank Li <Frank.Li@xxxxxxx>
Cc: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Cc: "Ilpo Järvinen" <ilpo.jarvinen@xxxxxxxxxxxxxxx>
Cc: Josef Bacik <josef@xxxxxxxxxxxxxx>
Cc: Hugo Villeneuve <hvilleneuve@xxxxxxxxxxxx>
Cc: stable <stable@xxxxxxxxxx>
Signed-off-by: Joshua Rogers <linux@xxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/tty/serial/8250/8250_core.c | 3 +++
drivers/tty/serial/8250/8250_omap.c | 3 +++
drivers/tty/serial/8250/8250_port.c | 3 +++
3 files changed, 9 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 5730ef97f836..af94ed4e633e 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -950,6 +950,9 @@ void serial8250_unregister_port(struct uart_8250_port *uart)
serial8250_em485_free(uart);
+ if (uart->overrun_backoff_time_ms)
+ cancel_delayed_work_sync(&uart->overrun_backoff);
+
uart_remove_one_port(&serial8250_reg, &uart->port);
if (serial8250_isa_devs) {
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 29a203ed93fd..07ebed6ac6c9 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -786,6 +786,9 @@ static void omap_8250_shutdown(struct uart_port *port)
disable_irq_nosync(port->irq);
+ if (up->overrun_backoff_time_ms)
+ cancel_delayed_work_sync(&up->overrun_backoff);
+
serial8250_release_dma(up);
up->dma = NULL;
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 4afebd96e062..710d2a28b918 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2497,6 +2497,9 @@ void serial8250_do_shutdown(struct uart_port *port)
synchronize_irq(port->irq);
+ if (up->overrun_backoff_time_ms)
+ cancel_delayed_work_sync(&up->overrun_backoff);
+
if (up->dma)
serial8250_release_dma(up);
--
2.56.0