linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jslaby@suse.com>
Cc: linux-kernel@vger.kernel.org,
	Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Subject: [PATCH v2 2/2] tty: use tty_init_dev_retry() to workaround a race condition
Date: Thu, 21 Nov 2019 15:22:39 +0000	[thread overview]
Message-ID: <20191121152239.28405-2-sudipm.mukherjee@gmail.com> (raw)
In-Reply-To: <20191121152239.28405-1-sudipm.mukherjee@gmail.com>

There seems to be a race condition in tty drivers and I could see on
many boot cycles a NULL pointer dereference as tty_init_dev() tries to
do 'tty->port->itty = tty' even though tty->port is NULL.
'tty->port' will be set by the driver and if the driver has not yet done
it before we open the tty device we can get to this situation. By adding
some extra debug prints, I noticed that:

6.650130: uart_add_one_port
6.663849: register_console
6.664846: tty_open
6.674391: tty_init_dev
6.675456: tty_port_link_device

uart_add_one_port() registers the console, as soon as it registers, the
userspace tries to use it and that leads to tty_open() but
uart_add_one_port() has not yet done tty_port_link_device() and so
tty->port is not yet configured when control reaches tty_init_dev().

So, add one retry and use tty_init_dev_retry().

Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
---

v1: had some hardcoded numbers which were difficult to understand.
https://lore.kernel.org/lkml/20191120151709.14148-2-sudipm.mukherjee@gmail.com/

I know this is not a proper fix, and the proper fix should have been to
have a lock. But that will be too intrusive and adding retry was a safer
option than that.

 drivers/tty/tty_io.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 95d7abeca254..f71a11895230 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1945,6 +1945,7 @@ EXPORT_SYMBOL_GPL(tty_kopen);
 /**
  *	tty_open_by_driver	-	open a tty device
  *	@device: dev_t of device to open
+ *	@retry: number of times to retry if tty_init_dev_retry fails
  *	@filp: file pointer to tty
  *
  *	Performs the driver lookup, checks for a reopen, or otherwise
@@ -1957,7 +1958,7 @@ EXPORT_SYMBOL_GPL(tty_kopen);
  *	  - concurrent tty driver removal w/ lookup
  *	  - concurrent tty removal from driver table
  */
-static struct tty_struct *tty_open_by_driver(dev_t device,
+static struct tty_struct *tty_open_by_driver(dev_t device, int retry,
 					     struct file *filp)
 {
 	struct tty_struct *tty;
@@ -2001,7 +2002,7 @@ static struct tty_struct *tty_open_by_driver(dev_t device,
 			tty = ERR_PTR(retval);
 		}
 	} else { /* Returns with the tty_lock held for now */
-		tty = tty_init_dev(driver, index);
+		tty = tty_init_dev_retry(driver, index, retry);
 		mutex_unlock(&tty_mutex);
 	}
 out:
@@ -2036,7 +2037,7 @@ static struct tty_struct *tty_open_by_driver(dev_t device,
 static int tty_open(struct inode *inode, struct file *filp)
 {
 	struct tty_struct *tty;
-	int noctty, retval;
+	int noctty, retval, retry = 1;
 	dev_t device = inode->i_rdev;
 	unsigned saved_flags = filp->f_flags;
 
@@ -2049,7 +2050,7 @@ static int tty_open(struct inode *inode, struct file *filp)
 
 	tty = tty_open_current_tty(device, filp);
 	if (!tty)
-		tty = tty_open_by_driver(device, filp);
+		tty = tty_open_by_driver(device, retry--, filp);
 
 	if (IS_ERR(tty)) {
 		tty_free_file(filp);
-- 
2.11.0


  reply	other threads:[~2019-11-21 15:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-21 15:22 [PATCH v2 1/2] tty: add retry capability to tty_init_dev() Sudip Mukherjee
2019-11-21 15:22 ` Sudip Mukherjee [this message]
2019-11-21 16:41   ` [PATCH v2 2/2] tty: use tty_init_dev_retry() to workaround a race condition Greg Kroah-Hartman
2019-11-21 21:01     ` Sudip Mukherjee
2019-11-22  9:05       ` Jiri Slaby
2019-11-22  9:11         ` Jiri Slaby
2019-11-24  0:02           ` Sudip Mukherjee
2019-11-25 10:42             ` Jiri Slaby
2019-12-10 11:41         ` Sudip Mukherjee
2019-12-12 11:15           ` Greg Kroah-Hartman
2019-12-17 11:47             ` Sudip Mukherjee
2019-12-17 12:05               ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191121152239.28405-2-sudipm.mukherjee@gmail.com \
    --to=sudipm.mukherjee@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jslaby@suse.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).