diff options
author | Alan Cox <alan@linux.intel.com> | 2009-06-11 09:03:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-11 11:51:06 -0400 |
commit | 26a2e20f4a966bebc312836aeb4423fbfd4e33e2 (patch) | |
tree | 69c2d9fc4eba1e62a66892173ea0a4c599768f12 /drivers/char/tty_ioctl.c | |
parent | 0b91421857414f525690ee452c0b0acb6ab1dba3 (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.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)) |