diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:38:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:41 -0400 |
commit | 8f520021837d45c47d0ab57e7271f8d88bf7f3a4 (patch) | |
tree | 4435f3141163480c23f7274c502d58e3cd9cb963 /drivers/char/tty_ioctl.c | |
parent | 1d65b4a088de407e99714fdc27862449db04fb5c (diff) |
tty: Termios locking - sort out real_tty confusions and lock reads
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>
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r-- | drivers/char/tty_ioctl.c | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 93bfa1d6cc92..30670851e51a 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -893,6 +893,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
893 | { | 893 | { |
894 | struct tty_struct *real_tty; | 894 | struct tty_struct *real_tty; |
895 | void __user *p = (void __user *)arg; | 895 | void __user *p = (void __user *)arg; |
896 | int ret = 0; | ||
896 | 897 | ||
897 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 898 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
898 | tty->driver->subtype == PTY_TYPE_MASTER) | 899 | tty->driver->subtype == PTY_TYPE_MASTER) |
@@ -928,18 +929,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
928 | return set_termios(real_tty, p, TERMIOS_OLD); | 929 | return set_termios(real_tty, p, TERMIOS_OLD); |
929 | #ifndef TCGETS2 | 930 | #ifndef TCGETS2 |
930 | case TCGETS: | 931 | case TCGETS: |
932 | mutex_lock(&real_tty->termios_mutex); | ||
931 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) | 933 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) |
932 | return -EFAULT; | 934 | ret = -EFAULT; |
933 | return 0; | 935 | mutex_unlock(&real_tty->termios_mutex); |
936 | return ret; | ||
934 | #else | 937 | #else |
935 | case TCGETS: | 938 | case TCGETS: |
939 | mutex_lock(&real_tty->termios_mutex); | ||
936 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) | 940 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) |
937 | return -EFAULT; | 941 | ret = -EFAULT; |
938 | return 0; | 942 | mutex_unlock(&real_tty->termios_mutex); |
943 | return ret; | ||
939 | case TCGETS2: | 944 | case TCGETS2: |
945 | mutex_lock(&real_tty->termios_mutex); | ||
940 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) | 946 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) |
941 | return -EFAULT; | 947 | ret = -EFAULT; |
942 | return 0; | 948 | mutex_unlock(&real_tty->termios_mutex); |
949 | return ret; | ||
943 | case TCSETSF2: | 950 | case TCSETSF2: |
944 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); | 951 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); |
945 | case TCSETSW2: | 952 | case TCSETSW2: |
@@ -957,36 +964,46 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
957 | return set_termios(real_tty, p, TERMIOS_TERMIO); | 964 | return set_termios(real_tty, p, TERMIOS_TERMIO); |
958 | #ifndef TCGETS2 | 965 | #ifndef TCGETS2 |
959 | case TIOCGLCKTRMIOS: | 966 | case TIOCGLCKTRMIOS: |
967 | mutex_lock(&real_tty->termios_mutex); | ||
960 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | 968 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) |
961 | return -EFAULT; | 969 | ret = -EFAULT; |
962 | return 0; | 970 | mutex_unlock(&real_tty->termios_mutex); |
971 | return ret; | ||
963 | case TIOCSLCKTRMIOS: | 972 | case TIOCSLCKTRMIOS: |
964 | if (!capable(CAP_SYS_ADMIN)) | 973 | if (!capable(CAP_SYS_ADMIN)) |
965 | return -EPERM; | 974 | return -EPERM; |
975 | mutex_lock(&real_tty->termios_mutex); | ||
966 | if (user_termios_to_kernel_termios(real_tty->termios_locked, | 976 | if (user_termios_to_kernel_termios(real_tty->termios_locked, |
967 | (struct termios __user *) arg)) | 977 | (struct termios __user *) arg)) |
968 | return -EFAULT; | 978 | ret = -EFAULT; |
969 | return 0; | 979 | mutex_unlock(&real_tty->termios_mutex); |
980 | return ret; | ||
970 | #else | 981 | #else |
971 | case TIOCGLCKTRMIOS: | 982 | case TIOCGLCKTRMIOS: |
983 | mutex_lock(&real_tty->termios_mutex); | ||
972 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | 984 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) |
973 | return -EFAULT; | 985 | ret = -EFAULT; |
974 | return 0; | 986 | mutex_unlock(&real_tty->termios_mutex); |
987 | return ret; | ||
975 | case TIOCSLCKTRMIOS: | 988 | case TIOCSLCKTRMIOS: |
976 | if (!capable(CAP_SYS_ADMIN)) | 989 | if (!capable(CAP_SYS_ADMIN)) |
977 | return -EPERM; | 990 | ret = -EPERM; |
991 | mutex_lock(&real_tty->termios_mutex); | ||
978 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, | 992 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, |
979 | (struct termios __user *) arg)) | 993 | (struct termios __user *) arg)) |
980 | return -EFAULT; | 994 | ret = -EFAULT; |
981 | return 0; | 995 | mutex_unlock(&real_tty->termios_mutex); |
996 | return ret; | ||
982 | #endif | 997 | #endif |
983 | #ifdef TCGETX | 998 | #ifdef TCGETX |
984 | case TCGETX: | 999 | case TCGETX: |
985 | if (real_tty->termiox == NULL) | 1000 | if (real_tty->termiox == NULL) |
986 | return -EINVAL; | 1001 | return -EINVAL; |
1002 | mutex_lock(&real_tty->termios_mutex); | ||
987 | if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) | 1003 | if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) |
988 | return -EFAULT; | 1004 | ret = -EFAULT; |
989 | return 0; | 1005 | mutex_unlock(&real_tty->termios_mutex); |
1006 | return ret; | ||
990 | case TCSETX: | 1007 | case TCSETX: |
991 | return set_termiox(real_tty, p, 0); | 1008 | return set_termiox(real_tty, p, 0); |
992 | case TCSETXW: | 1009 | case TCSETXW: |
@@ -995,10 +1012,11 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
995 | return set_termiox(real_tty, p, TERMIOS_FLUSH); | 1012 | return set_termiox(real_tty, p, TERMIOS_FLUSH); |
996 | #endif | 1013 | #endif |
997 | case TIOCGSOFTCAR: | 1014 | case TIOCGSOFTCAR: |
998 | /* FIXME: for correctness we may need to take the termios | 1015 | mutex_lock(&real_tty->termios_mutex); |
999 | lock here - review */ | 1016 | ret = put_user(C_CLOCAL(real_tty) ? 1 : 0, |
1000 | return put_user(C_CLOCAL(real_tty) ? 1 : 0, | ||
1001 | (int __user *)arg); | 1017 | (int __user *)arg); |
1018 | mutex_unlock(&real_tty->termios_mutex); | ||
1019 | return ret; | ||
1002 | case TIOCSSOFTCAR: | 1020 | case TIOCSSOFTCAR: |
1003 | if (get_user(arg, (unsigned int __user *) arg)) | 1021 | if (get_user(arg, (unsigned int __user *) arg)) |
1004 | return -EFAULT; | 1022 | return -EFAULT; |