Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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:
+38 −20
Original line number Diff line number Diff line
@@ -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)
@@ -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:
@@ -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:
@@ -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;