[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250430111617.1151390-1-quic_cxin@quicinc.com>
Date: Wed, 30 Apr 2025 19:16:17 +0800
From: Xin Chen <quic_cxin@...cinc.com>
To: Rob Herring <robh@...nel.org>,
Greg Kroah-Hartman
<gregkh@...uxfoundation.org>,
Jiri Slaby <jirislaby@...nel.org>
CC: <linux-serial@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
<liulzhao@....qualcomm.com>, <quic_chejiang@...cinc.com>,
<zaiyongc@....qualcomm.com>, <quic_zijuhu@...cinc.com>,
<quic_mohamull@...cinc.com>, Xin Chen <quic_cxin@...cinc.com>,
"Panicker
Harish" <quic_pharish@...cinc.com>
Subject: [PATCH v1] tty: serdev: serdev-ttyport: Fix use-after-free in ttyport_close() due to uninitialized serport->tty
When ttyport_open() fails to initialize a tty device, serport->tty is not
set to NULL, leading to a use-after-free scenario in ttyport_close().
To fix this, initialize serport->tty to NULL upon failure and check its
value before reading.
Call trace1:
release_tty
tty_init_dev
ttyport_open
serdev_device_open
qca_setup[hci_uart]
hci_uart_setup[hci_uart]
hci_dev_open_sync[bluetooth]
hci_dev_do_open[bluetooth]
hci_dev_open[bluetooth]
hci_sock_bind[bluetooth]
Call trace2:
refcount_warn_saturate
tty_lock
ttyport_close
serdev_device_close
hci_uart_close[hci_uart]
hci_dev_open_sync[bluetooth]
hci_dev_do_open[bluetooth]
hci_dev_open[bluetooth]
hci_sock_bind[bluetooth]
Co-developed-by: Panicker Harish <quic_pharish@...cinc.com>
Signed-off-by: Panicker Harish <quic_pharish@...cinc.com>
Signed-off-by: Xin Chen <quic_cxin@...cinc.com>
---
drivers/tty/serdev/serdev-ttyport.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index 3d7ae7fa5018..287908f2009b 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -88,6 +88,10 @@ static void ttyport_write_flush(struct serdev_controller *ctrl)
{
struct serport *serport = serdev_controller_get_drvdata(ctrl);
struct tty_struct *tty = serport->tty;
+ if (!tty) {
+ dev_err(&ctrl->dev, "tty is null\n");
+ return;
+ }
tty_driver_flush_buffer(tty);
}
@@ -108,8 +112,10 @@ static int ttyport_open(struct serdev_controller *ctrl)
int ret;
tty = tty_init_dev(serport->tty_drv, serport->tty_idx);
- if (IS_ERR(tty))
+ if (IS_ERR(tty)) {
+ serport->tty = NULL;
return PTR_ERR(tty);
+ }
serport->tty = tty;
if (!tty->ops->open || !tty->ops->close) {
@@ -156,6 +162,11 @@ static void ttyport_close(struct serdev_controller *ctrl)
clear_bit(SERPORT_ACTIVE, &serport->flags);
+ if (!tty) {
+ dev_err(&ctrl->dev, "tty is null\n");
+ return;
+ }
+
tty_lock(tty);
if (tty->ops->close)
tty->ops->close(tty, NULL);
--
2.34.1
Powered by blists - more mailing lists