aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_ioctl.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-06-11 09:03:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 11:51:06 -0400
commit26a2e20f4a966bebc312836aeb4423fbfd4e33e2 (patch)
tree69c2d9fc4eba1e62a66892173ea0a4c599768f12 /drivers/char/tty_ioctl.c
parent0b91421857414f525690ee452c0b0acb6ab1dba3 (diff)
tty: Untangle termios and mm mutex dependencies
Although this doesn't cause any problems it could potentially do so for future mmap using devices. No real work is needed to sort it out so untangle it before it causes problems Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r--drivers/char/tty_ioctl.c75
1 files changed, 46 insertions, 29 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 2401dbcbee9c..8116bb1c8f80 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -626,9 +626,25 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
626 return 0; 626 return 0;
627} 627}
628 628
629static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
630{
631 mutex_lock(&tty->termios_mutex);
632 memcpy(kterm, tty->termios, sizeof(struct ktermios));
633 mutex_unlock(&tty->termios_mutex);
634}
635
636static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
637{
638 mutex_lock(&tty->termios_mutex);
639 memcpy(kterm, tty->termios_locked, sizeof(struct ktermios));
640 mutex_unlock(&tty->termios_mutex);
641}
642
629static int get_termio(struct tty_struct *tty, struct termio __user *termio) 643static int get_termio(struct tty_struct *tty, struct termio __user *termio)
630{ 644{
631 if (kernel_termios_to_user_termio(termio, tty->termios)) 645 struct ktermios kterm;
646 copy_termios(tty, &kterm);
647 if (kernel_termios_to_user_termio(termio, &kterm))
632 return -EFAULT; 648 return -EFAULT;
633 return 0; 649 return 0;
634} 650}
@@ -930,6 +946,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
930 struct tty_struct *real_tty; 946 struct tty_struct *real_tty;
931 void __user *p = (void __user *)arg; 947 void __user *p = (void __user *)arg;
932 int ret = 0; 948 int ret = 0;
949 struct ktermios kterm;
950 struct termiox ktermx;
933 951
934 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 952 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
935 tty->driver->subtype == PTY_TYPE_MASTER) 953 tty->driver->subtype == PTY_TYPE_MASTER)
@@ -965,23 +983,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
965 return set_termios(real_tty, p, TERMIOS_OLD); 983 return set_termios(real_tty, p, TERMIOS_OLD);
966#ifndef TCGETS2 984#ifndef TCGETS2
967 case TCGETS: 985 case TCGETS:
968 mutex_lock(&real_tty->termios_mutex); 986 copy_termios(real_tty, &kterm);
969 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) 987 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
970 ret = -EFAULT; 988 ret = -EFAULT;
971 mutex_unlock(&real_tty->termios_mutex);
972 return ret; 989 return ret;
973#else 990#else
974 case TCGETS: 991 case TCGETS:
975 mutex_lock(&real_tty->termios_mutex); 992 copy_termios(real_tty, &kterm);
976 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) 993 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
977 ret = -EFAULT; 994 ret = -EFAULT;
978 mutex_unlock(&real_tty->termios_mutex);
979 return ret; 995 return ret;
980 case TCGETS2: 996 case TCGETS2:
981 mutex_lock(&real_tty->termios_mutex); 997 copy_termios(real_tty, &kterm);
982 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) 998 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
983 ret = -EFAULT; 999 ret = -EFAULT;
984 mutex_unlock(&real_tty->termios_mutex);
985 return ret; 1000 return ret;
986 case TCSETSF2: 1001 case TCSETSF2:
987 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); 1002 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
@@ -1000,34 +1015,36 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
1000 return set_termios(real_tty, p, TERMIOS_TERMIO); 1015 return set_termios(real_tty, p, TERMIOS_TERMIO);
1001#ifndef TCGETS2 1016#ifndef TCGETS2
1002 case TIOCGLCKTRMIOS: 1017 case TIOCGLCKTRMIOS:
1003 mutex_lock(&real_tty->termios_mutex); 1018 copy_termios_locked(real_tty, &kterm);
1004 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) 1019 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
1005 ret = -EFAULT; 1020 ret = -EFAULT;
1006 mutex_unlock(&real_tty->termios_mutex);
1007 return ret; 1021 return ret;
1008 case TIOCSLCKTRMIOS: 1022 case TIOCSLCKTRMIOS:
1009 if (!capable(CAP_SYS_ADMIN)) 1023 if (!capable(CAP_SYS_ADMIN))
1010 return -EPERM; 1024 return -EPERM;
1011 mutex_lock(&real_tty->termios_mutex); 1025 copy_termios_locked(real_tty, &kterm);
1012 if (user_termios_to_kernel_termios(real_tty->termios_locked, 1026 if (user_termios_to_kernel_termios(&kterm,
1013 (struct termios __user *) arg)) 1027 (struct termios __user *) arg))
1014 ret = -EFAULT; 1028 return -EFAULT;
1029 mutex_lock(&real_tty->termios_mutex);
1030 memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
1015 mutex_unlock(&real_tty->termios_mutex); 1031 mutex_unlock(&real_tty->termios_mutex);
1016 return ret; 1032 return 0;
1017#else 1033#else
1018 case TIOCGLCKTRMIOS: 1034 case TIOCGLCKTRMIOS:
1019 mutex_lock(&real_tty->termios_mutex); 1035 copy_termios_locked(real_tty, &kterm);
1020 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) 1036 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
1021 ret = -EFAULT; 1037 ret = -EFAULT;
1022 mutex_unlock(&real_tty->termios_mutex);
1023 return ret; 1038 return ret;
1024 case TIOCSLCKTRMIOS: 1039 case TIOCSLCKTRMIOS:
1025 if (!capable(CAP_SYS_ADMIN)) 1040 if (!capable(CAP_SYS_ADMIN))
1026 ret = -EPERM; 1041 return -EPERM;
1027 mutex_lock(&real_tty->termios_mutex); 1042 copy_termios_locked(real_tty, &kterm);
1028 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, 1043 if (user_termios_to_kernel_termios_1(&kterm,
1029 (struct termios __user *) arg)) 1044 (struct termios __user *) arg))
1030 ret = -EFAULT; 1045 return -EFAULT;
1046 mutex_lock(&real_tty->termios_mutex);
1047 memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
1031 mutex_unlock(&real_tty->termios_mutex); 1048 mutex_unlock(&real_tty->termios_mutex);
1032 return ret; 1049 return ret;
1033#endif 1050#endif
@@ -1036,9 +1053,10 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
1036 if (real_tty->termiox == NULL) 1053 if (real_tty->termiox == NULL)
1037 return -EINVAL; 1054 return -EINVAL;
1038 mutex_lock(&real_tty->termios_mutex); 1055 mutex_lock(&real_tty->termios_mutex);
1039 if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) 1056 memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
1040 ret = -EFAULT;
1041 mutex_unlock(&real_tty->termios_mutex); 1057 mutex_unlock(&real_tty->termios_mutex);
1058 if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1059 ret = -EFAULT;
1042 return ret; 1060 return ret;
1043 case TCSETX: 1061 case TCSETX:
1044 return set_termiox(real_tty, p, 0); 1062 return set_termiox(real_tty, p, 0);
@@ -1048,10 +1066,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
1048 return set_termiox(real_tty, p, TERMIOS_FLUSH); 1066 return set_termiox(real_tty, p, TERMIOS_FLUSH);
1049#endif 1067#endif
1050 case TIOCGSOFTCAR: 1068 case TIOCGSOFTCAR:
1051 mutex_lock(&real_tty->termios_mutex); 1069 copy_termios(real_tty, &kterm);
1052 ret = put_user(C_CLOCAL(real_tty) ? 1 : 0, 1070 ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
1053 (int __user *)arg); 1071 (int __user *)arg);
1054 mutex_unlock(&real_tty->termios_mutex);
1055 return ret; 1072 return ret;
1056 case TIOCSSOFTCAR: 1073 case TIOCSSOFTCAR:
1057 if (get_user(arg, (unsigned int __user *) arg)) 1074 if (get_user(arg, (unsigned int __user *) arg))