aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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))