patch "tty: Fix data race between tiocsti() and flush_to_ldisc()" added to tty-testing
Subsystems (2)
This is a note to let you know that I've just added the patch titled
tty: Fix data race between tiocsti() and flush_to_ldisc()
to my tty git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
in the tty-testing branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will be merged to the tty-next branch sometime soon, after it passes testing, and the merge window is open.
If you have any questions about this process, please let me know.
From bb2853a6a421a052268eee00fd5d3f6b3504b2b1 Mon Sep 17 00:00:00 2001
From: Nguyen Dinh Phi <[email protected]>
Date: Mon, 23 Aug 2021 08:06:41 +0800
Subject: tty: Fix data race between tiocsti() and flush_to_ldisc()
The ops->receive_buf() may be accessed concurrently from these two functions. If the driver flushes data to the line discipline receive_buf() method while tiocsti() is waiting for the ops->receive_buf() to finish its work, the data race will happen.
For example:tty_ioctl |tty_ldisc_receive_buf
->tioctsi | ->tty_port_default_receive_buf
| ->tty_ldisc_receive_buf
->hci_uart_tty_receive | ->hci_uart_tty_receive
->h4_recv | ->h4_recvIn this case, the h4 receive buffer will be overwritten by the latecomer, and we will lost the data.
Hence, change tioctsi() function to use the exclusive lock interface from tty_buffer to avoid the data race.
--- drivers/tty/tty_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/tty_io.c +2 -2
@@ -2290,8 +2290,6 @@ static int tty_fasync(int fd, struct file *filp, int on)* Locking: * Called functions take tty_ldiscs_lock * current->signal->tty check is safe without locks -* -* FIXME: may race normal receive processing */ static int tiocsti (struct tty_struct *tty,char __user *p)
@@ -2307,8 +2305,10 @@ static int tiocsti(struct tty_struct *tty, char __user *p) ld =tty_ldisc_ref_wait (tty);if (!ld)return -EIO ; +tty_buffer_lock_exclusive (tty->port);if (ld->ops->receive_buf) ld->ops->receive_buf (tty, &ch, &mbz,1 ); +tty_buffer_unlock_exclusive (tty->port);tty_ldisc_deref (ld);return 0 ; }
Signature · 1 line
2.32.0