diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/uaccess.h | 19 | ||||
-rw-r--r-- | arch/x86/kernel/i386_ksyms_32.c | 1 | ||||
-rw-r--r-- | arch/x86/lib/getuser.S | 37 |
3 files changed, 48 insertions, 9 deletions
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 1709801d18ec..1e963267d44e 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
@@ -151,8 +151,15 @@ extern int __get_user_bad(void); | |||
151 | * On error, the variable @x is set to zero. | 151 | * On error, the variable @x is set to zero. |
152 | */ | 152 | */ |
153 | #ifdef CONFIG_X86_32 | 153 | #ifdef CONFIG_X86_32 |
154 | #define __get_user_8(__ret_gu, __val_gu, ptr) \ | 154 | #define __get_user_8(ret, x, ptr) \ |
155 | __get_user_x(X, __ret_gu, __val_gu, ptr) | 155 | do { \ |
156 | register unsigned long long __xx asm("%edx"); \ | ||
157 | asm volatile("call __get_user_8" \ | ||
158 | : "=a" (ret), "=r" (__xx) \ | ||
159 | : "0" (ptr)); \ | ||
160 | (x) = __xx; \ | ||
161 | } while (0) | ||
162 | |||
156 | #else | 163 | #else |
157 | #define __get_user_8(__ret_gu, __val_gu, ptr) \ | 164 | #define __get_user_8(__ret_gu, __val_gu, ptr) \ |
158 | __get_user_x(8, __ret_gu, __val_gu, ptr) | 165 | __get_user_x(8, __ret_gu, __val_gu, ptr) |
@@ -162,6 +169,7 @@ extern int __get_user_bad(void); | |||
162 | ({ \ | 169 | ({ \ |
163 | int __ret_gu; \ | 170 | int __ret_gu; \ |
164 | unsigned long __val_gu; \ | 171 | unsigned long __val_gu; \ |
172 | unsigned long long __val_gu8; \ | ||
165 | __chk_user_ptr(ptr); \ | 173 | __chk_user_ptr(ptr); \ |
166 | might_fault(); \ | 174 | might_fault(); \ |
167 | switch (sizeof(*(ptr))) { \ | 175 | switch (sizeof(*(ptr))) { \ |
@@ -175,13 +183,16 @@ extern int __get_user_bad(void); | |||
175 | __get_user_x(4, __ret_gu, __val_gu, ptr); \ | 183 | __get_user_x(4, __ret_gu, __val_gu, ptr); \ |
176 | break; \ | 184 | break; \ |
177 | case 8: \ | 185 | case 8: \ |
178 | __get_user_8(__ret_gu, __val_gu, ptr); \ | 186 | __get_user_8(__ret_gu, __val_gu8, ptr); \ |
179 | break; \ | 187 | break; \ |
180 | default: \ | 188 | default: \ |
181 | __get_user_x(X, __ret_gu, __val_gu, ptr); \ | 189 | __get_user_x(X, __ret_gu, __val_gu, ptr); \ |
182 | break; \ | 190 | break; \ |
183 | } \ | 191 | } \ |
184 | (x) = (__typeof__(*(ptr)))__val_gu; \ | 192 | if (sizeof(*(ptr)) == 8) \ |
193 | (x) = (__typeof__(*(ptr)))__val_gu8; \ | ||
194 | else \ | ||
195 | (x) = (__typeof__(*(ptr)))__val_gu; \ | ||
185 | __ret_gu; \ | 196 | __ret_gu; \ |
186 | }) | 197 | }) |
187 | 198 | ||
diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index 9c3bd4a2050e..0fa69127209a 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c | |||
@@ -26,6 +26,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic); | |||
26 | EXPORT_SYMBOL(__get_user_1); | 26 | EXPORT_SYMBOL(__get_user_1); |
27 | EXPORT_SYMBOL(__get_user_2); | 27 | EXPORT_SYMBOL(__get_user_2); |
28 | EXPORT_SYMBOL(__get_user_4); | 28 | EXPORT_SYMBOL(__get_user_4); |
29 | EXPORT_SYMBOL(__get_user_8); | ||
29 | 30 | ||
30 | EXPORT_SYMBOL(__put_user_1); | 31 | EXPORT_SYMBOL(__put_user_1); |
31 | EXPORT_SYMBOL(__put_user_2); | 32 | EXPORT_SYMBOL(__put_user_2); |
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index 156b9c804670..d3bf9f99ca77 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S | |||
@@ -15,11 +15,10 @@ | |||
15 | * __get_user_X | 15 | * __get_user_X |
16 | * | 16 | * |
17 | * Inputs: %[r|e]ax contains the address. | 17 | * Inputs: %[r|e]ax contains the address. |
18 | * The register is modified, but all changes are undone | ||
19 | * before returning because the C code doesn't know about it. | ||
20 | * | 18 | * |
21 | * Outputs: %[r|e]ax is error code (0 or -EFAULT) | 19 | * Outputs: %[r|e]ax is error code (0 or -EFAULT) |
22 | * %[r|e]dx contains zero-extended value | 20 | * %[r|e]dx contains zero-extended value |
21 | * %ecx contains the high half for 32-bit __get_user_8 | ||
23 | * | 22 | * |
24 | * | 23 | * |
25 | * These functions should not modify any other registers, | 24 | * These functions should not modify any other registers, |
@@ -79,22 +78,35 @@ ENTRY(__get_user_4) | |||
79 | CFI_ENDPROC | 78 | CFI_ENDPROC |
80 | ENDPROC(__get_user_4) | 79 | ENDPROC(__get_user_4) |
81 | 80 | ||
82 | #ifdef CONFIG_X86_64 | ||
83 | ENTRY(__get_user_8) | 81 | ENTRY(__get_user_8) |
84 | CFI_STARTPROC | 82 | CFI_STARTPROC |
83 | #ifdef CONFIG_X86_64 | ||
85 | add $7,%_ASM_AX | 84 | add $7,%_ASM_AX |
86 | jc bad_get_user | 85 | jc bad_get_user |
87 | GET_THREAD_INFO(%_ASM_DX) | 86 | GET_THREAD_INFO(%_ASM_DX) |
88 | cmp TI_addr_limit(%_ASM_DX),%_ASM_AX | 87 | cmp TI_addr_limit(%_ASM_DX),%_ASM_AX |
89 | jae bad_get_user | 88 | jae bad_get_user |
90 | ASM_STAC | 89 | ASM_STAC |
91 | 4: movq -7(%_ASM_AX),%_ASM_DX | 90 | 4: movq -7(%_ASM_AX),%_ASM_DX |
92 | xor %eax,%eax | 91 | xor %eax,%eax |
93 | ASM_CLAC | 92 | ASM_CLAC |
94 | ret | 93 | ret |
94 | #else | ||
95 | add $7,%_ASM_AX | ||
96 | jc bad_get_user_8 | ||
97 | GET_THREAD_INFO(%_ASM_DX) | ||
98 | cmp TI_addr_limit(%_ASM_DX),%_ASM_AX | ||
99 | jae bad_get_user_8 | ||
100 | ASM_STAC | ||
101 | 4: mov -7(%_ASM_AX),%edx | ||
102 | 5: mov -3(%_ASM_AX),%ecx | ||
103 | xor %eax,%eax | ||
104 | ASM_CLAC | ||
105 | ret | ||
106 | #endif | ||
95 | CFI_ENDPROC | 107 | CFI_ENDPROC |
96 | ENDPROC(__get_user_8) | 108 | ENDPROC(__get_user_8) |
97 | #endif | 109 | |
98 | 110 | ||
99 | bad_get_user: | 111 | bad_get_user: |
100 | CFI_STARTPROC | 112 | CFI_STARTPROC |
@@ -105,9 +117,24 @@ bad_get_user: | |||
105 | CFI_ENDPROC | 117 | CFI_ENDPROC |
106 | END(bad_get_user) | 118 | END(bad_get_user) |
107 | 119 | ||
120 | #ifdef CONFIG_X86_32 | ||
121 | bad_get_user_8: | ||
122 | CFI_STARTPROC | ||
123 | xor %edx,%edx | ||
124 | xor %ecx,%ecx | ||
125 | mov $(-EFAULT),%_ASM_AX | ||
126 | ASM_CLAC | ||
127 | ret | ||
128 | CFI_ENDPROC | ||
129 | END(bad_get_user_8) | ||
130 | #endif | ||
131 | |||
108 | _ASM_EXTABLE(1b,bad_get_user) | 132 | _ASM_EXTABLE(1b,bad_get_user) |
109 | _ASM_EXTABLE(2b,bad_get_user) | 133 | _ASM_EXTABLE(2b,bad_get_user) |
110 | _ASM_EXTABLE(3b,bad_get_user) | 134 | _ASM_EXTABLE(3b,bad_get_user) |
111 | #ifdef CONFIG_X86_64 | 135 | #ifdef CONFIG_X86_64 |
112 | _ASM_EXTABLE(4b,bad_get_user) | 136 | _ASM_EXTABLE(4b,bad_get_user) |
137 | #else | ||
138 | _ASM_EXTABLE(4b,bad_get_user_8) | ||
139 | _ASM_EXTABLE(5b,bad_get_user_8) | ||
113 | #endif | 140 | #endif |