From db0054fe613b21cd65c1609680cc47c520760044 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Sun, 4 Oct 2015 19:29:12 +0200 Subject: [PATCH] drivers/tty: require read access for controlling terminal commit 0c55627167870255158db1cde0d28366f91c8872 upstream. This is mostly a hardening fix, given that write-only access to other users' ttys is usually only given through setgid tty executables. Signed-off-by: Jann Horn Signed-off-by: Greg Kroah-Hartman [bwh: Backported to 3.2: - __proc_set_tty() also takes a task_struct pointer] Signed-off-by: Ben Hutchings --- drivers/tty/tty_io.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index fa59fbeebabc..6ab03229c837 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1985,8 +1985,24 @@ got_driver: if (!noctty && current->signal->leader && !current->signal->tty && - tty->session == NULL) - __proc_set_tty(current, tty); + tty->session == NULL) { + /* + * Don't let a process that only has write access to the tty + * obtain the privileges associated with having a tty as + * controlling terminal (being able to reopen it with full + * access through /dev/tty, being able to perform pushback). + * Many distributions set the group of all ttys to "tty" and + * grant write-only access to all terminals for setgid tty + * binaries, which should not imply full privileges on all ttys. + * + * This could theoretically break old code that performs open() + * on a write-only file descriptor. In that case, it might be + * necessary to also permit this if + * inode_permission(inode, MAY_READ) == 0. + */ + if (filp->f_mode & FMODE_READ) + __proc_set_tty(current, tty); + } spin_unlock_irq(¤t->sighand->siglock); tty_unlock(); mutex_unlock(&tty_mutex); @@ -2266,7 +2282,7 @@ static int fionbio(struct file *file, int __user *p) * Takes ->siglock() when updating signal->tty */ -static int tiocsctty(struct tty_struct *tty, int arg) +static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) { int ret = 0; if (current->signal->leader && (task_session(current) == tty->session)) @@ -2299,6 +2315,13 @@ static int tiocsctty(struct tty_struct *tty, int arg) goto unlock; } } + + /* See the comment in tty_open(). */ + if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) { + ret = -EPERM; + goto unlock; + } + proc_set_tty(current, tty); unlock: mutex_unlock(&tty_mutex); @@ -2653,7 +2676,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) no_tty(); return 0; case TIOCSCTTY: - return tiocsctty(tty, arg); + return tiocsctty(tty, file, arg); case TIOCGPGRP: return tiocgpgrp(tty, real_tty, p); case TIOCSPGRP: -- 2.39.2