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
|
||
|
|