@@ -96,27 +96,58 @@ static inline unsigned long __untagged_addr_remote(struct mm_struct *mm, unsigne
96
96
* call.
97
97
*/
98
98
99
- #define __get_user_asm (insn , x , ptr , err ) \
99
+ #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
100
+ #define __get_user_asm (insn , x , ptr , label ) \
101
+ asm_goto_output( \
102
+ "1:\n" \
103
+ " " insn " %0, %1\n" \
104
+ _ASM_EXTABLE_UACCESS_ERR(1b, %l2, %0) \
105
+ : "=&r" (x) \
106
+ : "m" (*(ptr)) : : label)
107
+ #else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
108
+ #define __get_user_asm (insn , x , ptr , label ) \
100
109
do { \
101
- __typeof__(x) __x ; \
110
+ long __gua_err = 0 ; \
102
111
__asm__ __volatile__ ( \
103
112
"1:\n" \
104
113
" " insn " %1, %2\n" \
105
114
"2:\n" \
106
115
_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1) \
107
- : "+r" (err ), "=&r" (__x ) \
116
+ : "+r" (__gua_err ), "=&r" (x ) \
108
117
: "m" (*(ptr))); \
109
- (x) = __x; \
118
+ if (__gua_err) \
119
+ goto label; \
110
120
} while (0)
121
+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
111
122
112
123
#ifdef CONFIG_64BIT
113
- #define __get_user_8 (x , ptr , err ) \
114
- __get_user_asm("ld", x, ptr, err )
124
+ #define __get_user_8 (x , ptr , label ) \
125
+ __get_user_asm("ld", x, ptr, label )
115
126
#else /* !CONFIG_64BIT */
116
- #define __get_user_8 (x , ptr , err ) \
127
+
128
+ #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
129
+ #define __get_user_8 (x , ptr , label ) \
130
+ u32 __user *__ptr = (u32 __user *)(ptr); \
131
+ u32 __lo, __hi; \
132
+ asm_goto_output( \
133
+ "1:\n" \
134
+ " lw %0, %2\n" \
135
+ "2:\n" \
136
+ " lw %1, %3\n" \
137
+ _ASM_EXTABLE_UACCESS_ERR(1b, %l4, %0) \
138
+ _ASM_EXTABLE_UACCESS_ERR(2b, %l4, %0) \
139
+ : "=&r" (__lo), "=r" (__hi) \
140
+ : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]) \
141
+ : : label); \
142
+ (x) = (__typeof__(x))((__typeof__((x) - (x)))( \
143
+ (((u64)__hi << 32) | __lo))); \
144
+
145
+ #else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
146
+ #define __get_user_8 (x , ptr , label ) \
117
147
do { \
118
148
u32 __user *__ptr = (u32 __user *)(ptr); \
119
149
u32 __lo, __hi; \
150
+ long __gu8_err = 0; \
120
151
__asm__ __volatile__ ( \
121
152
"1:\n" \
122
153
" lw %1, %3\n" \
@@ -125,35 +156,51 @@ do { \
125
156
"3:\n" \
126
157
_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \
127
158
_ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \
128
- : "+r" (err ), "=&r" (__lo), "=r" (__hi) \
159
+ : "+r" (__gu8_err ), "=&r" (__lo), "=r" (__hi) \
129
160
: "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \
130
- if (err) \
161
+ if (__gu8_err) { \
131
162
__hi = 0; \
132
- (x) = (__typeof__(x))((__typeof__((x)-(x)))( \
163
+ goto label; \
164
+ } \
165
+ (x) = (__typeof__(x))((__typeof__((x) - (x)))( \
133
166
(((u64)__hi << 32) | __lo))); \
134
167
} while (0)
168
+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
169
+
135
170
#endif /* CONFIG_64BIT */
136
171
137
- #define __get_user_nocheck (x , __gu_ptr , __gu_err ) \
172
+ #define __get_user_nocheck (x , __gu_ptr , label ) \
138
173
do { \
139
174
switch (sizeof(*__gu_ptr)) { \
140
175
case 1: \
141
- __get_user_asm("lb", (x), __gu_ptr, __gu_err ); \
176
+ __get_user_asm("lb", (x), __gu_ptr, label ); \
142
177
break; \
143
178
case 2: \
144
- __get_user_asm("lh", (x), __gu_ptr, __gu_err ); \
179
+ __get_user_asm("lh", (x), __gu_ptr, label ); \
145
180
break; \
146
181
case 4: \
147
- __get_user_asm("lw", (x), __gu_ptr, __gu_err ); \
182
+ __get_user_asm("lw", (x), __gu_ptr, label ); \
148
183
break; \
149
184
case 8: \
150
- __get_user_8((x), __gu_ptr, __gu_err); \
185
+ __get_user_8((x), __gu_ptr, label); \
151
186
break; \
152
187
default: \
153
188
BUILD_BUG(); \
154
189
} \
155
190
} while (0)
156
191
192
+ #define __get_user_error (x , ptr , err ) \
193
+ do { \
194
+ __label__ __gu_failed; \
195
+ \
196
+ __get_user_nocheck(x, ptr, __gu_failed); \
197
+ err = 0; \
198
+ break; \
199
+ __gu_failed: \
200
+ x = 0; \
201
+ err = -EFAULT; \
202
+ } while (0)
203
+
157
204
/**
158
205
* __get_user: - Get a simple variable from user space, with less checking.
159
206
* @x: Variable to store result.
@@ -178,13 +225,16 @@ do { \
178
225
({ \
179
226
const __typeof__(*(ptr)) __user *__gu_ptr = untagged_addr(ptr); \
180
227
long __gu_err = 0; \
228
+ __typeof__(x) __gu_val; \
181
229
\
182
230
__chk_user_ptr(__gu_ptr); \
183
231
\
184
232
__enable_user_access(); \
185
- __get_user_nocheck(x , __gu_ptr, __gu_err); \
233
+ __get_user_error(__gu_val , __gu_ptr, __gu_err); \
186
234
__disable_user_access(); \
187
235
\
236
+ (x) = __gu_val; \
237
+ \
188
238
__gu_err; \
189
239
})
190
240
@@ -369,13 +419,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
369
419
}
370
420
371
421
#define __get_kernel_nofault (dst , src , type , err_label ) \
372
- do { \
373
- long __kr_err = 0; \
374
- \
375
- __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \
376
- if (unlikely(__kr_err)) \
377
- goto err_label; \
378
- } while (0)
422
+ __get_user_nocheck(*((type *)(dst)), (type *)(src), err_label)
379
423
380
424
#define __put_kernel_nofault (dst , src , type , err_label ) \
381
425
__put_user_nocheck(*((type *)(src)), (type *)(dst), err_label)
@@ -401,12 +445,9 @@ static inline void user_access_restore(unsigned long enabled) { }
401
445
__put_user_nocheck(x, (ptr), label)
402
446
403
447
#define unsafe_get_user (x , ptr , label ) do { \
404
- long __err = 0; \
405
448
__inttype(*(ptr)) __gu_val; \
406
- __get_user_nocheck(__gu_val, (ptr), __err ); \
449
+ __get_user_nocheck(__gu_val, (ptr), label ); \
407
450
(x) = (__force __typeof__(*(ptr)))__gu_val; \
408
- if (__err) \
409
- goto label; \
410
451
} while (0)
411
452
412
453
#define unsafe_copy_loop (dst , src , len , type , op , label ) \
0 commit comments