]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
tty: Termios locking - sort out real_tty confusions and lock reads
authorAlan Cox <alan@redhat.com>
Mon, 13 Oct 2008 09:38:46 +0000 (10:38 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Oct 2008 16:51:41 +0000 (09:51 -0700)
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>
drivers/char/tty_io.c
drivers/char/tty_ioctl.c

index fa162c93ee025a89188856da71ffdf54a3ffc4aa..ac53d7f9b5d4d159511b8ce80d0d32defbb86b66 100644 (file)
@@ -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:
index 93bfa1d6cc92301e38cca48dbf99086a6dce2e78..30670851e51aa0a7d2fc058f9187b78efe2d9827 100644 (file)
@@ -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;