diff options
author | Arnd Bergmann <arnd@arndb.de> | 2009-06-18 15:48:19 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-06-18 17:39:58 -0400 |
commit | 69d5ffdaad7b77b97229b55c36afb20e5bebd29e (patch) | |
tree | ce7f174f423bd84bd974abd3b8c6b9ae94fdc6cf | |
parent | 06f5013aa8eb5895ced2c71d13f5114103605555 (diff) |
x86: convert termios.h to the asm-generic version
This patch turned out more controversial than expected
and may get dropped in the future. I'm including it
for reference anyway.
The user_termio_to_kernel_termios and kernel_termios_to_user_termio
functions on x86 are lacking error checking from get_user and
are not portable to big-endian systems, so the asm-generic
header has to differ in this regard.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
LKML-Reference: <cover.1245354003.git.arnd@arndb.de>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | arch/x86/include/asm/termios.h | 86 |
1 files changed, 63 insertions, 23 deletions
diff --git a/arch/x86/include/asm/termios.h b/arch/x86/include/asm/termios.h index c4ee8056baca..d0922adc56d4 100644 --- a/arch/x86/include/asm/termios.h +++ b/arch/x86/include/asm/termios.h | |||
@@ -1,5 +1,12 @@ | |||
1 | #ifndef _ASM_X86_TERMIOS_H | 1 | #ifndef _ASM_GENERIC_TERMIOS_H |
2 | #define _ASM_X86_TERMIOS_H | 2 | #define _ASM_GENERIC_TERMIOS_H |
3 | /* | ||
4 | * Most architectures have straight copies of the x86 code, with | ||
5 | * varying levels of bug fixes on top. Usually it's a good idea | ||
6 | * to use this generic version instead, but be careful to avoid | ||
7 | * ABI changes. | ||
8 | * New architectures should not provide their own version. | ||
9 | */ | ||
3 | 10 | ||
4 | #include <asm/termbits.h> | 11 | #include <asm/termbits.h> |
5 | #include <asm/ioctls.h> | 12 | #include <asm/ioctls.h> |
@@ -54,37 +61,57 @@ struct termio { | |||
54 | /* | 61 | /* |
55 | * Translate a "termio" structure into a "termios". Ugh. | 62 | * Translate a "termio" structure into a "termios". Ugh. |
56 | */ | 63 | */ |
57 | #define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ | ||
58 | unsigned short __tmp; \ | ||
59 | get_user(__tmp,&(termio)->x); \ | ||
60 | *(unsigned short *) &(termios)->x = __tmp; \ | ||
61 | } | ||
62 | |||
63 | static inline int user_termio_to_kernel_termios(struct ktermios *termios, | 64 | static inline int user_termio_to_kernel_termios(struct ktermios *termios, |
64 | struct termio __user *termio) | 65 | const struct termio __user *termio) |
65 | { | 66 | { |
66 | SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); | 67 | unsigned short tmp; |
67 | SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); | 68 | |
68 | SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); | 69 | if (get_user(tmp, &termio->c_iflag) < 0) |
69 | SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); | 70 | goto fault; |
70 | get_user(termios->c_line, &termio->c_line); | 71 | termios->c_iflag = (0xffff0000 & termios->c_iflag) | tmp; |
71 | return copy_from_user(termios->c_cc, termio->c_cc, NCC); | 72 | |
73 | if (get_user(tmp, &termio->c_oflag) < 0) | ||
74 | goto fault; | ||
75 | termios->c_oflag = (0xffff0000 & termios->c_oflag) | tmp; | ||
76 | |||
77 | if (get_user(tmp, &termio->c_cflag) < 0) | ||
78 | goto fault; | ||
79 | termios->c_cflag = (0xffff0000 & termios->c_cflag) | tmp; | ||
80 | |||
81 | if (get_user(tmp, &termio->c_lflag) < 0) | ||
82 | goto fault; | ||
83 | termios->c_lflag = (0xffff0000 & termios->c_lflag) | tmp; | ||
84 | |||
85 | if (get_user(termios->c_line, &termio->c_line) < 0) | ||
86 | goto fault; | ||
87 | |||
88 | if (copy_from_user(termios->c_cc, termio->c_cc, NCC) != 0) | ||
89 | goto fault; | ||
90 | |||
91 | return 0; | ||
92 | |||
93 | fault: | ||
94 | return -EFAULT; | ||
72 | } | 95 | } |
73 | 96 | ||
74 | /* | 97 | /* |
75 | * Translate a "termios" structure into a "termio". Ugh. | 98 | * Translate a "termios" structure into a "termio". Ugh. |
76 | */ | 99 | */ |
77 | static inline int kernel_termios_to_user_termio(struct termio __user *termio, | 100 | static inline int kernel_termios_to_user_termio(struct termio __user *termio, |
78 | struct ktermios *termios) | 101 | struct ktermios *termios) |
79 | { | 102 | { |
80 | put_user((termios)->c_iflag, &(termio)->c_iflag); | 103 | if (put_user(termios->c_iflag, &termio->c_iflag) < 0 || |
81 | put_user((termios)->c_oflag, &(termio)->c_oflag); | 104 | put_user(termios->c_oflag, &termio->c_oflag) < 0 || |
82 | put_user((termios)->c_cflag, &(termio)->c_cflag); | 105 | put_user(termios->c_cflag, &termio->c_cflag) < 0 || |
83 | put_user((termios)->c_lflag, &(termio)->c_lflag); | 106 | put_user(termios->c_lflag, &termio->c_lflag) < 0 || |
84 | put_user((termios)->c_line, &(termio)->c_line); | 107 | put_user(termios->c_line, &termio->c_line) < 0 || |
85 | return copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); | 108 | copy_to_user(termio->c_cc, termios->c_cc, NCC) != 0) |
109 | return -EFAULT; | ||
110 | |||
111 | return 0; | ||
86 | } | 112 | } |
87 | 113 | ||
114 | #ifdef TCGETS2 | ||
88 | static inline int user_termios_to_kernel_termios(struct ktermios *k, | 115 | static inline int user_termios_to_kernel_termios(struct ktermios *k, |
89 | struct termios2 __user *u) | 116 | struct termios2 __user *u) |
90 | { | 117 | { |
@@ -108,7 +135,20 @@ static inline int kernel_termios_to_user_termios_1(struct termios __user *u, | |||
108 | { | 135 | { |
109 | return copy_to_user(u, k, sizeof(struct termios)); | 136 | return copy_to_user(u, k, sizeof(struct termios)); |
110 | } | 137 | } |
138 | #else /* TCGETS2 */ | ||
139 | static inline int user_termios_to_kernel_termios(struct ktermios *k, | ||
140 | struct termios __user *u) | ||
141 | { | ||
142 | return copy_from_user(k, u, sizeof(struct termios)); | ||
143 | } | ||
144 | |||
145 | static inline int kernel_termios_to_user_termios(struct termios __user *u, | ||
146 | struct ktermios *k) | ||
147 | { | ||
148 | return copy_to_user(u, k, sizeof(struct termios)); | ||
149 | } | ||
150 | #endif /* TCGETS2 */ | ||
111 | 151 | ||
112 | #endif /* __KERNEL__ */ | 152 | #endif /* __KERNEL__ */ |
113 | 153 | ||
114 | #endif /* _ASM_X86_TERMIOS_H */ | 154 | #endif /* _ASM_GENERIC_TERMIOS_H */ |