* [PATCH] Bluetooth: hci_ldisc: Fix for pty driver
@ 2019-01-25 3:55 Myungho Jung
2019-01-25 7:42 ` Marcel Holtmann
0 siblings, 1 reply; 2+ messages in thread
From: Myungho Jung @ 2019-01-25 3:55 UTC (permalink / raw)
To: Marcel Holtmann, Johan Hedberg; +Cc: linux-bluetooth, linux-kernel
tty_set_termios() should be called with slave side of pty driver. So, If
tty driver is pty master, it needs to be switched to ->link. Also,
tiocmget() and tiocmset() operations are optional so we need NULL check
for some drivers missing the operations like pty.
Reported-by: syzbot+a950165cbb86bdd023a4@syzkaller.appspotmail.com
Signed-off-by: Myungho Jung <mhjungk@gmail.com>
---
drivers/bluetooth/hci_ldisc.c | 76 +++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 30 deletions(-)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index fbf7b4df23ab..169dde91b3d3 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -299,10 +299,18 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
+/* If driver is pty master, return slave side */
+static struct tty_struct *hci_uart_get_real_tty(struct tty_struct *tty)
+{
+ return (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+ tty->driver->subtype == PTY_TYPE_MASTER) ? tty->link : tty;
+}
+
/* Flow control or un-flow control the device */
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
{
struct tty_struct *tty = hu->tty;
+ struct tty_struct *real_tty;
struct ktermios ktermios;
int status;
unsigned int set = 0;
@@ -314,45 +322,52 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
return;
}
+ real_tty = hci_uart_get_real_tty(tty);
if (enable) {
/* Disable hardware flow control */
- ktermios = tty->termios;
+ ktermios = real_tty->termios;
ktermios.c_cflag &= ~CRTSCTS;
- status = tty_set_termios(tty, &ktermios);
+ status = tty_set_termios(real_tty, &ktermios);
BT_DBG("Disabling hardware flow control: %s",
status ? "failed" : "success");
- /* Clear RTS to prevent the device from sending */
- /* Most UARTs need OUT2 to enable interrupts */
- status = tty->driver->ops->tiocmget(tty);
- BT_DBG("Current tiocm 0x%x", status);
-
- set &= ~(TIOCM_OUT2 | TIOCM_RTS);
- clear = ~set;
- set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
- TIOCM_OUT2 | TIOCM_LOOP;
- clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
- TIOCM_OUT2 | TIOCM_LOOP;
- status = tty->driver->ops->tiocmset(tty, set, clear);
- BT_DBG("Clearing RTS: %s", status ? "failed" : "success");
+ if (tty->driver->ops->tiocmget && tty->driver->ops->tiocmset) {
+ /* Clear RTS to prevent the device from sending */
+ /* Most UARTs need OUT2 to enable interrupts */
+ status = tty->driver->ops->tiocmget(tty);
+ BT_DBG("Current tiocm 0x%x", status);
+
+ set &= ~(TIOCM_OUT2 | TIOCM_RTS);
+ clear = ~set;
+ set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
+ TIOCM_OUT2 | TIOCM_LOOP;
+ clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
+ TIOCM_OUT2 | TIOCM_LOOP;
+ status = tty->driver->ops->tiocmset(tty, set, clear);
+ BT_DBG("Clearing RTS: %s", status ? "failed" :
+ "success");
+ }
} else {
- /* Set RTS to allow the device to send again */
- status = tty->driver->ops->tiocmget(tty);
- BT_DBG("Current tiocm 0x%x", status);
-
- set |= (TIOCM_OUT2 | TIOCM_RTS);
- clear = ~set;
- set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
- TIOCM_OUT2 | TIOCM_LOOP;
- clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
- TIOCM_OUT2 | TIOCM_LOOP;
- status = tty->driver->ops->tiocmset(tty, set, clear);
- BT_DBG("Setting RTS: %s", status ? "failed" : "success");
+ if (tty->driver->ops->tiocmget && tty->driver->ops->tiocmset) {
+ /* Set RTS to allow the device to send again */
+ status = tty->driver->ops->tiocmget(tty);
+ BT_DBG("Current tiocm 0x%x", status);
+
+ set |= (TIOCM_OUT2 | TIOCM_RTS);
+ clear = ~set;
+ set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
+ TIOCM_OUT2 | TIOCM_LOOP;
+ clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
+ TIOCM_OUT2 | TIOCM_LOOP;
+ status = tty->driver->ops->tiocmset(tty, set, clear);
+ BT_DBG("Setting RTS: %s", status ? "failed" :
+ "success");
+ }
/* Re-enable hardware flow control */
- ktermios = tty->termios;
+ ktermios = real_tty->termios;
ktermios.c_cflag |= CRTSCTS;
- status = tty_set_termios(tty, &ktermios);
+ status = tty_set_termios(real_tty, &ktermios);
BT_DBG("Enabling hardware flow control: %s",
status ? "failed" : "success");
}
@@ -367,9 +382,10 @@ void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
- struct tty_struct *tty = hu->tty;
+ struct tty_struct *tty;
struct ktermios ktermios;
+ tty = hci_uart_get_real_tty(hu->tty);
ktermios = tty->termios;
ktermios.c_cflag &= ~CBAUD;
tty_termios_encode_baud_rate(&ktermios, speed, speed);
--
2.17.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] Bluetooth: hci_ldisc: Fix for pty driver
2019-01-25 3:55 [PATCH] Bluetooth: hci_ldisc: Fix for pty driver Myungho Jung
@ 2019-01-25 7:42 ` Marcel Holtmann
0 siblings, 0 replies; 2+ messages in thread
From: Marcel Holtmann @ 2019-01-25 7:42 UTC (permalink / raw)
To: Myungho Jung; +Cc: Johan Hedberg, linux-bluetooth, linux-kernel
Hi Myungho,
> tty_set_termios() should be called with slave side of pty driver. So, If
> tty driver is pty master, it needs to be switched to ->link. Also,
> tiocmget() and tiocmset() operations are optional so we need NULL check
> for some drivers missing the operations like pty.
these are two independent fixes. Please turn them into two patches.
Regards
Marcel
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-01-25 7:42 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-25 3:55 [PATCH] Bluetooth: hci_ldisc: Fix for pty driver Myungho Jung
2019-01-25 7:42 ` Marcel Holtmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).