@@ -96,27 +96,58 @@ static inline unsigned long __untagged_addr_remote(struct mm_struct *mm, unsigne
9696 * call.
9797 */
9898
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 ) \
100109do { \
101- __typeof__(x) __x ; \
110+ long __gua_err = 0 ; \
102111 __asm__ __volatile__ ( \
103112 "1:\n" \
104113 " " insn " %1, %2\n" \
105114 "2:\n" \
106115 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1) \
107- : "+r" (err ), "=&r" (__x ) \
116+ : "+r" (__gua_err ), "=&r" (x ) \
108117 : "m" (*(ptr))); \
109- (x) = __x; \
118+ if (__gua_err) \
119+ goto label; \
110120} while (0)
121+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
111122
112123#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 )
115126#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 ) \
117147do { \
118148 u32 __user *__ptr = (u32 __user *)(ptr); \
119149 u32 __lo, __hi; \
150+ long __gu8_err = 0; \
120151 __asm__ __volatile__ ( \
121152 "1:\n" \
122153 " lw %1, %3\n" \
@@ -125,35 +156,51 @@ do { \
125156 "3:\n" \
126157 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \
127158 _ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \
128- : "+r" (err ), "=&r" (__lo), "=r" (__hi) \
159+ : "+r" (__gu8_err ), "=&r" (__lo), "=r" (__hi) \
129160 : "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \
130- if (err) \
161+ if (__gu8_err) { \
131162 __hi = 0; \
132- (x) = (__typeof__(x))((__typeof__((x)-(x)))( \
163+ goto label; \
164+ } \
165+ (x) = (__typeof__(x))((__typeof__((x) - (x)))( \
133166 (((u64)__hi << 32) | __lo))); \
134167} while (0)
168+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
169+
135170#endif /* CONFIG_64BIT */
136171
137- #define __get_user_nocheck (x , __gu_ptr , __gu_err ) \
172+ #define __get_user_nocheck (x , __gu_ptr , label ) \
138173do { \
139174 switch (sizeof(*__gu_ptr)) { \
140175 case 1: \
141- __get_user_asm("lb", (x), __gu_ptr, __gu_err ); \
176+ __get_user_asm("lb", (x), __gu_ptr, label ); \
142177 break; \
143178 case 2: \
144- __get_user_asm("lh", (x), __gu_ptr, __gu_err ); \
179+ __get_user_asm("lh", (x), __gu_ptr, label ); \
145180 break; \
146181 case 4: \
147- __get_user_asm("lw", (x), __gu_ptr, __gu_err ); \
182+ __get_user_asm("lw", (x), __gu_ptr, label ); \
148183 break; \
149184 case 8: \
150- __get_user_8((x), __gu_ptr, __gu_err); \
185+ __get_user_8((x), __gu_ptr, label); \
151186 break; \
152187 default: \
153188 BUILD_BUG(); \
154189 } \
155190} while (0)
156191
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+
157204/**
158205 * __get_user: - Get a simple variable from user space, with less checking.
159206 * @x: Variable to store result.
@@ -178,13 +225,16 @@ do { \
178225({ \
179226 const __typeof__(*(ptr)) __user *__gu_ptr = untagged_addr(ptr); \
180227 long __gu_err = 0; \
228+ __typeof__(x) __gu_val; \
181229 \
182230 __chk_user_ptr(__gu_ptr); \
183231 \
184232 __enable_user_access(); \
185- __get_user_nocheck(x , __gu_ptr, __gu_err); \
233+ __get_user_error(__gu_val , __gu_ptr, __gu_err); \
186234 __disable_user_access(); \
187235 \
236+ (x) = __gu_val; \
237+ \
188238 __gu_err; \
189239})
190240
@@ -369,13 +419,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
369419}
370420
371421#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)
379423
380424#define __put_kernel_nofault (dst , src , type , err_label ) \
381425 __put_user_nocheck(*((type *)(src)), (type *)(dst), err_label)
@@ -401,12 +445,9 @@ static inline void user_access_restore(unsigned long enabled) { }
401445 __put_user_nocheck(x, (ptr), label)
402446
403447#define unsafe_get_user (x , ptr , label ) do { \
404- long __err = 0; \
405448 __inttype(*(ptr)) __gu_val; \
406- __get_user_nocheck(__gu_val, (ptr), __err ); \
449+ __get_user_nocheck(__gu_val, (ptr), label ); \
407450 (x) = (__force __typeof__(*(ptr)))__gu_val; \
408- if (__err) \
409- goto label; \
410451} while (0)
411452
412453#define unsafe_copy_loop (dst , src , len , type , op , label ) \
0 commit comments