bluetooth: Fix WARNING in tty_set_termios()
PATCH v5 1/1 bluetooth: Fix WARNING in tty_set_termios()
tty_set_termios() has the following WARN_ON which can be triggered with a syscall to invoke TIOCSETD __NR_ioctl.
WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
Reference: https://syzkaller.appspot.com/bug?id=2410d22f1d8e5984217329dd0884b01d99e3e48d
"The problem started with commit 7721383f4199 ("Bluetooth: hci_uart: Support operational speed during setup") which introduced a new way for how tty_set_termios() could end up being called for a master pty."
Fix hci_uart_tty_open() to check if tty supports set_termios in addition to write and error out, if it doesn't.
--- drivers/bluetooth/hci_ldisc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/bluetooth/hci_ldisc.c +3 -3
@@ -474,10 +474,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)BT_DBG ("tty %p" , tty); -/* Error if the tty has no write op instead of leaving an exploitable -* hole +/* Error if the tty has no write/set_termios ops instead of leaving +* an exploitable hole. */ -if (tty->ops->write ==NULL ) +if (!tty->ops->write || !tty->ops->set_termios)return -EOPNOTSUPP ; hu =kzalloc (sizeof (struct hci_uart ),GFP_KERNEL );
Signature · 1 line
2.17.1
Quoted 28 lines · Shuah Khan
tty_set_termios()has the followingWARN_ONwhich can be triggered with a syscall to invoke TIOCSETD__NR_ioctl.WARN_ON(tty->driver->type ==
TTY_DRIVER_TYPE_PTY&&tty->driver->subtype == PTY_TYPE_MASTER);Reference: https://syzkaller.appspot.com/bug?id=2410d22f1d8e5984217329dd0884b01d99e3e48d
"The problem started with commit
7721383f4199("Bluetooth:hci_uart: Support operational speed during setup") which introduced a new way for howtty_set_termios()could end up being called for a master pty."Fix
hci_uart_tty_open()to check if tty supportsset_termiosin addition to write and error out, if it doesn't.Reported-by [email protected]Cc Johan Hovold <[email protected]>Cc Marcel Holtmann <[email protected]>Cc Al Viro <[email protected]>Signed-off-by Shuah Khan <[email protected]>--- drivers/bluetooth/hci_ldisc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/bluetooth/hci_ldisc.c +0
-0
drivers/bluetooth/hci_ldisc.c static int hci_uart_tty_open(struct tty_struct *tty) · line 478
Quoted 7 lines
drivers/bluetooth/hci_ldisc.c +2
-2@@ -474,10 +474,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)BT_DBG ("tty %p" , tty); -/* Error if the tty has no write op instead of leaving an exploitable -* hole +/* Error if the tty has no write/set_termios ops instead of leaving +* an exploitable hole.
Why do you think that a tty driver not implementing set_termios() is exploitable?
Note that tty_set_termios() handles a missing set_termios() callback just fine without dereferencing a NULL-pointer.
drivers/bluetooth/hci_ldisc.c static int hci_uart_tty_open(struct tty_struct *tty) · line 481
Quoted 4 lines
drivers/bluetooth/hci_ldisc.c +1
-1*/ -if (tty->ops->write ==NULL ) +if (!tty->ops->write || !tty->ops->set_termios)return -EOPNOTSUPP ;
I know Marcel asked you do implement things like this, but what you're really doing is to try to uphold the invariant that tty_set_termios() should never be called for a pty master. The WARN_ON in that function was put in place to make sure line-disciplines use the correct ioctl helpers (and the commit I pointed you to earlier in the paragraph you quote in the commit message broke that invariant).
I'm afraid this is totally obscured by the above change and misleading comment update.
Johan
Quoted 54 lines · Johan Hovold
Quoted 28 lines · Shuah Khan
tty_set_termios()has the followingWARN_ONwhich can be triggered with a syscall to invoke TIOCSETD__NR_ioctl.WARN_ON(tty->driver->type ==
TTY_DRIVER_TYPE_PTY&&tty->driver->subtype == PTY_TYPE_MASTER);Reference: https://syzkaller.appspot.com/bug?id=2410d22f1d8e5984217329dd0884b01d99e3e48d
"The problem started with commit
7721383f4199("Bluetooth:hci_uart: Support operational speed during setup") which introduced a new way for howtty_set_termios()could end up being called for a master pty."Fix
hci_uart_tty_open()to check if tty supportsset_termiosin addition to write and error out, if it doesn't.Reported-by [email protected]Cc Johan Hovold <[email protected]>Cc Marcel Holtmann <[email protected]>Cc Al Viro <[email protected]>Signed-off-by Shuah Khan <[email protected]>--- drivers/bluetooth/hci_ldisc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/bluetooth/hci_ldisc.c +0
-0drivers/bluetooth/hci_ldisc.c static int hci_uart_tty_open(struct tty_struct *tty) · line 478
Quoted 7 lines
drivers/bluetooth/hci_ldisc.c +2
-2@@ -474,10 +474,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)BT_DBG ("tty %p" , tty); -/* Error if the tty has no write op instead of leaving an exploitable -* hole +/* Error if the tty has no write/set_termios ops instead of leaving +* an exploitable hole. Why do you think that a tty driver not implementing
set_termios()is exploitable?Note that
tty_set_termios()handles a missingset_termios()callback just fine without dereferencing a NULL-pointer. >drivers/bluetooth/hci_ldisc.c static int hci_uart_tty_open(struct tty_struct *tty) · line 481
Quoted 4 lines
drivers/bluetooth/hci_ldisc.c +1
-1*/ -if (tty->ops->write ==NULL ) +if (!tty->ops->write || !tty->ops->set_termios)return -EOPNOTSUPP ;I know Marcel asked you do implement things like this, but what you're really doing is to try to uphold the invariant that
tty_set_termios()should never be called for a pty master. TheWARN_ONin that function was put in place to make sure line-disciplines use the correct ioctl helpers (and the commit I pointed you to earlier in the paragraph you quote in the commit message broke that invariant).
Quoted 3 lines
I'm afraid this is totally obscured by the above change and misleading comment update.
We are discussing the right fix for a while now. :)
I did two versions of the patch
1. Check set_termios in hci_uart_tty_open() based on Marcel's suggestion
2. Checks tty type in hci_uart_tty_open()
Both fix the problem I can reproduce on my system, however, I think checking tty type is the right way to fix this problem.
The reason is that tty type is the direct and definitive way to check if ldisc sets are supported ir unsupported.
Checking set_termios is an indirect way and I am not sure that it would work in all cases.
That being said, I will wait for some consensus on how to fix the problem, before I send another version of this patch.
thanks,
-- Shuah