summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2026-09-10 14:51:14 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-23 11:59:31 +0200
commitb48820de8c1a596c5b99775524dfce73c6576c5d (patch)
treebad0e8cb25d1c6106160ec91935f9cb41d6914c8 /include/linux
parent56964f6a31238fb41d5830bb42520c5b10ff7d8f (diff)
tty: port: fix tty_port_tty_vhangup() race
Drivers rely on tty_port_tty_vhangup() to synchronously hang up their ports before tearing down resources as part of deregistration (e.g. on physical disconnect). If tty_port_tty_vhangup() races with another hangup it may however return before the port has been shut down. This is in turn can lead to use-after-free and NULL-pointer dereferences in racing ioctls (including a synchronous hangup) and in processing of racing asynchronous hangups (carrier loss). Add the missing serialisation to tty_port_tty_vhangup() and tty_port_hangup() so that the former does not return until the port has been shut down also when there is a racing hangup. Note that serial core does not use tty_port_hangup(), but it already holds the port mutex when clearing port->tty and shutting down the port in uart_hangup(). Fixes: 7ca0ff9ab321 ("tty: Add a full port_close function") Cc: stable@kernel.org # 2.6.32: 2b5eac0f8c6e: tty: introduce and use tty_port_tty_vhangup() helper Cc: stable@kernel.org # 2.6.32 Reported-by: syzbot+5fabc1ae99ff40690d84@syzkaller.appspotmail.com Link: https://lore.kernel.org/6a944641.4d659fcc.734b4.003c.GAE@google.com Signed-off-by: Johan Hovold <johan@kernel.org> Link: https://patch.msgid.link/20260910125114.640880-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/tty_port.h22
1 files changed, 2 insertions, 20 deletions
diff --git a/include/linux/tty_port.h b/include/linux/tty_port.h
index 23cad403bb8f..8d22c59c6f15 100644
--- a/include/linux/tty_port.h
+++ b/include/linux/tty_port.h
@@ -245,7 +245,8 @@ bool tty_port_carrier_raised(struct tty_port *port);
void tty_port_raise_dtr_rts(struct tty_port *port);
void tty_port_lower_dtr_rts(struct tty_port *port);
void tty_port_hangup(struct tty_port *port);
-void __tty_port_tty_hangup(struct tty_port *port, bool check_clocal, bool async);
+void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
+void tty_port_tty_vhangup(struct tty_port *port);
void tty_port_tty_wakeup(struct tty_port *port);
int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty,
struct file *filp);
@@ -264,25 +265,6 @@ static inline int tty_port_users(struct tty_port *port)
return port->count + port->blocked_open;
}
-/**
- * tty_port_tty_hangup - helper to hang up a tty asynchronously
- * @port: tty port
- * @check_clocal: hang only ttys with %CLOCAL unset?
- */
-static inline void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
-{
- __tty_port_tty_hangup(port, check_clocal, true);
-}
-
-/**
- * tty_port_tty_vhangup - helper to hang up a tty synchronously
- * @port: tty port
- */
-static inline void tty_port_tty_vhangup(struct tty_port *port)
-{
- __tty_port_tty_hangup(port, false, false);
-}
-
#ifdef CONFIG_TTY
void tty_kref_put(struct tty_struct *tty);
__DEFINE_CLASS_IS_CONDITIONAL(tty_port_tty, true);