69 lines
2.1 KiB
Diff
69 lines
2.1 KiB
Diff
From 938f50fc744cb49892bd42c8f56bdfa63e82a27d Mon Sep 17 00:00:00 2001
|
|
From: Peter Hurley <peter@hurleysoftware.com>
|
|
Date: Sun, 10 Jan 2016 22:40:55 -0800
|
|
Subject: [PATCH] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD)
|
|
|
|
ioctl(TIOCGETD) retrieves the line discipline id directly from the
|
|
ldisc because the line discipline id (c_line) in termios is untrustworthy;
|
|
userspace may have set termios via ioctl(TCSETS*) without actually
|
|
changing the line discipline via ioctl(TIOCSETD).
|
|
|
|
However, directly accessing the current ldisc via tty->ldisc is
|
|
unsafe; the ldisc ptr dereferenced may be stale if the line discipline
|
|
is changing via ioctl(TIOCSETD) or hangup.
|
|
|
|
Wait for the line discipline reference (just like read() or write())
|
|
to retrieve the "current" line discipline id.
|
|
|
|
Cc: <stable@vger.kernel.org>
|
|
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
|
|
---
|
|
drivers/tty/tty_io.c | 24 +++++++++++++++++++++++-
|
|
1 file changed, 23 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
|
|
index f435977de740..bd4027e36910 100644
|
|
--- a/drivers/tty/tty_io.c
|
|
+++ b/drivers/tty/tty_io.c
|
|
@@ -2654,6 +2654,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
|
|
}
|
|
|
|
/**
|
|
+ * tiocgetd - get line discipline
|
|
+ * @tty: tty device
|
|
+ * @p: pointer to user data
|
|
+ *
|
|
+ * Retrieves the line discipline id directly from the ldisc.
|
|
+ *
|
|
+ * Locking: waits for ldisc reference (in case the line discipline
|
|
+ * is changing or the tty is being hungup)
|
|
+ */
|
|
+
|
|
+static int tiocgetd(struct tty_struct *tty, int __user *p)
|
|
+{
|
|
+ struct tty_ldisc *ld;
|
|
+ int ret;
|
|
+
|
|
+ ld = tty_ldisc_ref_wait(tty);
|
|
+ ret = put_user(ld->ops->num, p);
|
|
+ tty_ldisc_deref(ld);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
* send_break - performed time break
|
|
* @tty: device to break on
|
|
* @duration: timeout in mS
|
|
@@ -2879,7 +2901,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
case TIOCGSID:
|
|
return tiocgsid(tty, real_tty, p);
|
|
case TIOCGETD:
|
|
- return put_user(tty->ldisc->ops->num, (int __user *)p);
|
|
+ return tiocgetd(tty, p);
|
|
case TIOCSETD:
|
|
return tiocsetd(tty, p);
|
|
case TIOCVHANGUP:
|
|
--
|
|
2.5.0
|
|
|