Commit db0054fe authored by Jann Horn's avatar Jann Horn Committed by Ben Hutchings

drivers/tty: require read access for controlling terminal

commit 0c556271 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: default avatarJann Horn <jann@thejh.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.2:
 - __proc_set_tty() also takes a task_struct pointer]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 80910ccd
...@@ -1985,8 +1985,24 @@ static int tty_open(struct inode *inode, struct file *filp) ...@@ -1985,8 +1985,24 @@ static int tty_open(struct inode *inode, struct file *filp)
if (!noctty && if (!noctty &&
current->signal->leader && current->signal->leader &&
!current->signal->tty && !current->signal->tty &&
tty->session == NULL) tty->session == NULL) {
__proc_set_tty(current, tty); /*
* 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(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
tty_unlock(); tty_unlock();
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
...@@ -2266,7 +2282,7 @@ static int fionbio(struct file *file, int __user *p) ...@@ -2266,7 +2282,7 @@ static int fionbio(struct file *file, int __user *p)
* Takes ->siglock() when updating signal->tty * 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; int ret = 0;
if (current->signal->leader && (task_session(current) == tty->session)) if (current->signal->leader && (task_session(current) == tty->session))
...@@ -2299,6 +2315,13 @@ static int tiocsctty(struct tty_struct *tty, int arg) ...@@ -2299,6 +2315,13 @@ static int tiocsctty(struct tty_struct *tty, int arg)
goto unlock; 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); proc_set_tty(current, tty);
unlock: unlock:
mutex_unlock(&tty_mutex); mutex_unlock(&tty_mutex);
...@@ -2653,7 +2676,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -2653,7 +2676,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
no_tty(); no_tty();
return 0; return 0;
case TIOCSCTTY: case TIOCSCTTY:
return tiocsctty(tty, arg); return tiocsctty(tty, file, arg);
case TIOCGPGRP: case TIOCGPGRP:
return tiocgpgrp(tty, real_tty, p); return tiocgpgrp(tty, real_tty, p);
case TIOCSPGRP: case TIOCSPGRP:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment