Commit 8f520021 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: Termios locking - sort out real_tty confusions and lock reads

This moves us towards sanity and should mean our termios locking is now
complete and comprehensive.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1d65b4a0
...@@ -2605,7 +2605,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -2605,7 +2605,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCSTI: case TIOCSTI:
return tiocsti(tty, p); return tiocsti(tty, p);
case TIOCGWINSZ: case TIOCGWINSZ:
return tiocgwinsz(tty, p); return tiocgwinsz(real_tty, p);
case TIOCSWINSZ: case TIOCSWINSZ:
return tiocswinsz(tty, real_tty, p); return tiocswinsz(tty, real_tty, p);
case TIOCCONS: case TIOCCONS:
......
...@@ -893,6 +893,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, ...@@ -893,6 +893,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
{ {
struct tty_struct *real_tty; struct tty_struct *real_tty;
void __user *p = (void __user *)arg; void __user *p = (void __user *)arg;
int ret = 0;
if (tty->driver->type == TTY_DRIVER_TYPE_PTY && if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER) tty->driver->subtype == PTY_TYPE_MASTER)
...@@ -928,18 +929,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, ...@@ -928,18 +929,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termios(real_tty, p, TERMIOS_OLD); return set_termios(real_tty, p, TERMIOS_OLD);
#ifndef TCGETS2 #ifndef TCGETS2
case TCGETS: case TCGETS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
#else #else
case TCGETS: case TCGETS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
case TCGETS2: case TCGETS2:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
case TCSETSF2: case TCSETSF2:
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
case TCSETSW2: case TCSETSW2:
...@@ -957,36 +964,46 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, ...@@ -957,36 +964,46 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termios(real_tty, p, TERMIOS_TERMIO); return set_termios(real_tty, p, TERMIOS_TERMIO);
#ifndef TCGETS2 #ifndef TCGETS2
case TIOCGLCKTRMIOS: case TIOCGLCKTRMIOS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
case TIOCSLCKTRMIOS: case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
mutex_lock(&real_tty->termios_mutex);
if (user_termios_to_kernel_termios(real_tty->termios_locked, if (user_termios_to_kernel_termios(real_tty->termios_locked,
(struct termios __user *) arg)) (struct termios __user *) arg))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
#else #else
case TIOCGLCKTRMIOS: case TIOCGLCKTRMIOS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
case TIOCSLCKTRMIOS: case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; ret = -EPERM;
mutex_lock(&real_tty->termios_mutex);
if (user_termios_to_kernel_termios_1(real_tty->termios_locked, if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
(struct termios __user *) arg)) (struct termios __user *) arg))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
#endif #endif
#ifdef TCGETX #ifdef TCGETX
case TCGETX: case TCGETX:
if (real_tty->termiox == NULL) if (real_tty->termiox == NULL)
return -EINVAL; return -EINVAL;
mutex_lock(&real_tty->termios_mutex);
if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
return -EFAULT; ret = -EFAULT;
return 0; mutex_unlock(&real_tty->termios_mutex);
return ret;
case TCSETX: case TCSETX:
return set_termiox(real_tty, p, 0); return set_termiox(real_tty, p, 0);
case TCSETXW: case TCSETXW:
...@@ -995,10 +1012,11 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, ...@@ -995,10 +1012,11 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termiox(real_tty, p, TERMIOS_FLUSH); return set_termiox(real_tty, p, TERMIOS_FLUSH);
#endif #endif
case TIOCGSOFTCAR: case TIOCGSOFTCAR:
/* FIXME: for correctness we may need to take the termios mutex_lock(&real_tty->termios_mutex);
lock here - review */ ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
return put_user(C_CLOCAL(real_tty) ? 1 : 0,
(int __user *)arg); (int __user *)arg);
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TIOCSSOFTCAR: case TIOCSSOFTCAR:
if (get_user(arg, (unsigned int __user *) arg)) if (get_user(arg, (unsigned int __user *) arg))
return -EFAULT; return -EFAULT;
......
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