|
@@ -2128,8 +2128,24 @@ retry_open:
|
|
|
if (!noctty &&
|
|
|
current->signal->leader &&
|
|
|
!current->signal->tty &&
|
|
|
- tty->session == NULL)
|
|
|
- __proc_set_tty(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(tty);
|
|
|
+ }
|
|
|
spin_unlock_irq(¤t->sighand->siglock);
|
|
|
read_unlock(&tasklist_lock);
|
|
|
tty_unlock(tty);
|
|
@@ -2418,7 +2434,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;
|
|
|
|
|
@@ -2452,6 +2468,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(tty);
|
|
|
unlock:
|
|
|
read_unlock(&tasklist_lock);
|
|
@@ -2844,7 +2867,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:
|
|
@@ -3151,13 +3174,18 @@ struct class *tty_class;
|
|
|
static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
|
|
|
unsigned int index, unsigned int count)
|
|
|
{
|
|
|
+ int err;
|
|
|
+
|
|
|
/* init here, since reused cdevs cause crashes */
|
|
|
driver->cdevs[index] = cdev_alloc();
|
|
|
if (!driver->cdevs[index])
|
|
|
return -ENOMEM;
|
|
|
- cdev_init(driver->cdevs[index], &tty_fops);
|
|
|
+ driver->cdevs[index]->ops = &tty_fops;
|
|
|
driver->cdevs[index]->owner = driver->owner;
|
|
|
- return cdev_add(driver->cdevs[index], dev, count);
|
|
|
+ err = cdev_add(driver->cdevs[index], dev, count);
|
|
|
+ if (err)
|
|
|
+ kobject_put(&driver->cdevs[index]->kobj);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/**
|