diff options
-rw-r--r-- | drivers/char/tty_ioctl.c | 75 |
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 | ||
629 | static 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 | |||
636 | static 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 | |||
629 | static int get_termio(struct tty_struct *tty, struct termio __user *termio) | 643 | static 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)) |