Skip to content

Commit 69d5ffd

Browse files
arndbH. Peter Anvin
authored andcommitted
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>
1 parent 06f5013 commit 69d5ffd

File tree

1 file changed

+63
-23
lines changed

1 file changed

+63
-23
lines changed

arch/x86/include/asm/termios.h

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
#ifndef _ASM_X86_TERMIOS_H
2-
#define _ASM_X86_TERMIOS_H
1+
#ifndef _ASM_GENERIC_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+
*/
310

411
#include <asm/termbits.h>
512
#include <asm/ioctls.h>
@@ -54,37 +61,57 @@ struct termio {
5461
/*
5562
* Translate a "termio" structure into a "termios". Ugh.
5663
*/
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-
6364
static inline int user_termio_to_kernel_termios(struct ktermios *termios,
64-
struct termio __user *termio)
65+
const struct termio __user *termio)
6566
{
66-
SET_LOW_TERMIOS_BITS(termios, termio, c_iflag);
67-
SET_LOW_TERMIOS_BITS(termios, termio, c_oflag);
68-
SET_LOW_TERMIOS_BITS(termios, termio, c_cflag);
69-
SET_LOW_TERMIOS_BITS(termios, termio, c_lflag);
70-
get_user(termios->c_line, &termio->c_line);
71-
return copy_from_user(termios->c_cc, termio->c_cc, NCC);
67+
unsigned short tmp;
68+
69+
if (get_user(tmp, &termio->c_iflag) < 0)
70+
goto fault;
71+
termios->c_iflag = (0xffff0000 & termios->c_iflag) | tmp;
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;
7295
}
7396

7497
/*
7598
* Translate a "termios" structure into a "termio". Ugh.
7699
*/
77100
static inline int kernel_termios_to_user_termio(struct termio __user *termio,
78-
struct ktermios *termios)
101+
struct ktermios *termios)
79102
{
80-
put_user((termios)->c_iflag, &(termio)->c_iflag);
81-
put_user((termios)->c_oflag, &(termio)->c_oflag);
82-
put_user((termios)->c_cflag, &(termio)->c_cflag);
83-
put_user((termios)->c_lflag, &(termio)->c_lflag);
84-
put_user((termios)->c_line, &(termio)->c_line);
85-
return copy_to_user((termio)->c_cc, (termios)->c_cc, NCC);
103+
if (put_user(termios->c_iflag, &termio->c_iflag) < 0 ||
104+
put_user(termios->c_oflag, &termio->c_oflag) < 0 ||
105+
put_user(termios->c_cflag, &termio->c_cflag) < 0 ||
106+
put_user(termios->c_lflag, &termio->c_lflag) < 0 ||
107+
put_user(termios->c_line, &termio->c_line) < 0 ||
108+
copy_to_user(termio->c_cc, termios->c_cc, NCC) != 0)
109+
return -EFAULT;
110+
111+
return 0;
86112
}
87113

114+
#ifdef TCGETS2
88115
static inline int user_termios_to_kernel_termios(struct ktermios *k,
89116
struct termios2 __user *u)
90117
{
@@ -108,7 +135,20 @@ static inline int kernel_termios_to_user_termios_1(struct termios __user *u,
108135
{
109136
return copy_to_user(u, k, sizeof(struct termios));
110137
}
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 */
111151

112152
#endif /* __KERNEL__ */
113153

114-
#endif /* _ASM_X86_TERMIOS_H */
154+
#endif /* _ASM_GENERIC_TERMIOS_H */

0 commit comments

Comments
 (0)