Skip to content

Commit

Permalink
tty: Termios locking - sort out real_tty confusions and lock reads
Browse files Browse the repository at this point in the history
This moves us towards sanity and should mean our termios locking is now
complete and comprehensive.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Alan Cox authored and Linus Torvalds committed Oct 13, 2008
1 parent 1d65b4a commit 8f52002
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
2 changes: 1 addition & 1 deletion drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2605,7 +2605,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCSTI:
return tiocsti(tty, p);
case TIOCGWINSZ:
return tiocgwinsz(tty, p);
return tiocgwinsz(real_tty, p);
case TIOCSWINSZ:
return tiocswinsz(tty, real_tty, p);
case TIOCCONS:
Expand Down
58 changes: 38 additions & 20 deletions drivers/char/tty_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
{
struct tty_struct *real_tty;
void __user *p = (void __user *)arg;
int ret = 0;

if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
Expand Down Expand Up @@ -928,18 +929,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termios(real_tty, p, TERMIOS_OLD);
#ifndef TCGETS2
case TCGETS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
#else
case TCGETS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TCGETS2:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TCSETSF2:
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
case TCSETSW2:
Expand All @@ -957,36 +964,46 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termios(real_tty, p, TERMIOS_TERMIO);
#ifndef TCGETS2
case TIOCGLCKTRMIOS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TIOCSLCKTRMIOS:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
mutex_lock(&real_tty->termios_mutex);
if (user_termios_to_kernel_termios(real_tty->termios_locked,
(struct termios __user *) arg))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
#else
case TIOCGLCKTRMIOS:
mutex_lock(&real_tty->termios_mutex);
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TIOCSLCKTRMIOS:
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,
(struct termios __user *) arg))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
#endif
#ifdef TCGETX
case TCGETX:
if (real_tty->termiox == NULL)
return -EINVAL;
mutex_lock(&real_tty->termios_mutex);
if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
return -EFAULT;
return 0;
ret = -EFAULT;
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TCSETX:
return set_termiox(real_tty, p, 0);
case TCSETXW:
Expand All @@ -995,10 +1012,11 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
return set_termiox(real_tty, p, TERMIOS_FLUSH);
#endif
case TIOCGSOFTCAR:
/* FIXME: for correctness we may need to take the termios
lock here - review */
return put_user(C_CLOCAL(real_tty) ? 1 : 0,
mutex_lock(&real_tty->termios_mutex);
ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
(int __user *)arg);
mutex_unlock(&real_tty->termios_mutex);
return ret;
case TIOCSSOFTCAR:
if (get_user(arg, (unsigned int __user *) arg))
return -EFAULT;
Expand Down

0 comments on commit 8f52002

Please sign in to comment.