FAILED: patch "[PATCH] tty: fix data race between tty_init_dev and flush of buf" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
b027e2298bd588d6fa36ed2eda97447fb3eac078Mon Sep 17 00:00:00 2001
From: Gaurav Kohli <[email protected]>
Date: Tue, 23 Jan 2018 13:16:34 +0530
Subject: [PATCH] tty: fix data race between tty_init_dev and flush of buf
There can be a race, if receive_buf call comes before tty initialization completes in n_tty_open and tty->disc_data may be NULL.
CPU0 CPU1
---- ----
000|n_tty_receive_buf_common() n_tty_open() -001|n_tty_receive_buf2() tty_ldisc_open.isra.3() -002|tty_ldisc_receive_buf(inline) tty_ldisc_setup()
Using ldisc semaphore lock in tty_init_dev till disc_data initializes completely.
drivers/tty/tty_io.c +7 -1
@@ -1323,6 +1323,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n" , __func__, tty->driver->name); + retval =tty_ldisc_lock (tty,5 *HZ ); +if (retval) + goto err_release_lock; tty->port->itty = tty;/*
@@ -1333,6 +1336,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) retval =tty_ldisc_setup (tty, tty->link);if (retval) goto err_release_tty; +tty_ldisc_unlock (tty);/* Return the tty locked so that it cannot vanish under the caller */ return tty;
@@ -1345,9 +1349,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)/* call the tty release_tty routine to clean out this slot */ err_release_tty: -tty_unlock (tty); +tty_ldisc_unlock (tty);tty_info_ratelimited (tty,"ldisc open failed (%d), clearing slot %d\n" , retval, idx); +err_release_lock: +tty_unlock (tty);release_tty (tty, idx);return ERR_PTR (retval); }
drivers/tty/tty_ldisc.c +2 -2
@@ -337,7 +337,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty)ldsem_up_write (&tty->ldisc_sem); } -static int tty_ldisc_lock (struct tty_struct *tty,unsigned long timeout) +int tty_ldisc_lock (struct tty_struct *tty,unsigned long timeout) {int ret;
@@ -348,7 +348,7 @@ static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)return 0 ; } -static void tty_ldisc_unlock (struct tty_struct *tty) +void tty_ldisc_unlock (struct tty_struct *tty) {clear_bit (TTY_LDISC_HALTED , &tty->flags);__tty_ldisc_unlock (tty);
include/linux/tty.h +2 -0
@@ -405,6 +405,8 @@ extern const char *tty_name(const struct tty_struct *tty);extern struct tty_struct *tty_kopen (dev_t device);extern void tty_kclose (struct tty_struct *tty);extern int tty_dev_name_to_number (const char *name,dev_t *number); +extern int tty_ldisc_lock (struct tty_struct *tty,unsigned long timeout); +extern void tty_ldisc_unlock (struct tty_struct *tty);#else static inline void tty_kref_put (struct tty_struct *tty) { }