mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
serial: core: shut down initialized port on removal
When a serial port configured as a console is opened and subsequently closed, tty_port_shutdown() skips invoking port->ops->shutdown() because port->console is true. As a result, tty_port_initialized() remains true and the port's interrupt handler stays registered in the irq subsystem. If the underlying device is later unbound or removed (e.g. via sysfs driver unbind or device hot-unplug), serial_core_remove_one_port() unregisters the console, frees uport->name via kfree(), and tears down the port without shutting it down or freeing its IRQ. Consequently, the irqaction descriptor remains registered in genirq with action->name pointing to freed memory. This triggers a use-after-free read whenever genirq accesses action->name, such as when reading /proc/interrupts: BUG: KASAN: slab-use-after-free in string+0x476/0x570 Call Trace: string+0x476/0x570 vsnprintf+0x422/0x1300 seq_printf+0x... show_interrupts+... Fix this by acquiring port->mutex in serial_core_remove_one_port() after console unregistration, clearing port->console under the mutex to prevent data races with concurrent tty_port_shutdown(), and invoking uart_shutdown(NULL, state) if the port remains initialized. This ensures that port->ops->shutdown() is called and the IRQ is freed before kfree(uport->name). Reported-by: syzbot+843bf2f48f4d12e6682e@syzkaller.appspotmail.com Cc: stable <stable@kernel.org> Closes: https://syzkaller.appspot.com/bug?extid=843bf2f48f4d12e6682e Fixes:761ed4a945("tty: serial_core: convert uart_close to use tty_port_close") Fixes:f7048b1590("tty: serial_core: Add name field to uart_port struct") Signed-off-by: Igor Putko <igorpetindev@gmail.com> Link: https://patch.msgid.link/20261003163337.45577-1-igorpetindev@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
408001136b
commit
810d467c11
|
|
@ -3239,6 +3239,13 @@ static void serial_core_remove_one_port(struct uart_driver *drv,
|
|||
if (uart_console(uport))
|
||||
unregister_console(uport->cons);
|
||||
|
||||
scoped_guard(mutex, &port->mutex) {
|
||||
port->console = false;
|
||||
|
||||
if (tty_port_initialized(port))
|
||||
uart_shutdown(NULL, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the port IO and memory resources, if any.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user