ASM GOTO is miscompiled by GCC when it is used inside a auto cleanup scope:

bool foo(u32 __user *p, u32 val)
{
        scoped_guard(pagefault)
                unsafe_put_user(val, p, efault);
        return true;
efault:
        return false;
}

It ends up leaking the pagefault disable counter in the fault path. clang
at least fails the build.

Rename unsafe_*_user() to arch_unsafe_*_user() which makes the generic
uaccess header wrap it with a local label that makes both compilers emit
correct code. Same for the kernel_nofault() variants.

Signed-off-by: Thomas Gleixner <[email protected]>
Cc: [email protected]
---
 arch/x86/include/asm/uaccess.h |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -528,18 +528,18 @@ static __must_check __always_inline bool
 #define user_access_save()     smap_save()
 #define user_access_restore(x) smap_restore(x)
 
-#define unsafe_put_user(x, ptr, label) \
+#define arch_unsafe_put_user(x, ptr, label)    \
        __put_user_size((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), label)
 
 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
-#define unsafe_get_user(x, ptr, err_label)                                     
\
+#define arch_unsafe_get_user(x, ptr, err_label)                                
        \
 do {                                                                           
\
        __inttype(*(ptr)) __gu_val;                                             
\
        __get_user_size(__gu_val, (ptr), sizeof(*(ptr)), err_label);            
\
        (x) = (__force __typeof__(*(ptr)))__gu_val;                             
\
 } while (0)
 #else // !CONFIG_CC_HAS_ASM_GOTO_OUTPUT
-#define unsafe_get_user(x, ptr, err_label)                                     
\
+#define arch_unsafe_get_user(x, ptr, err_label)                                
        \
 do {                                                                           
\
        int __gu_err;                                                           
\
        __inttype(*(ptr)) __gu_val;                                             
\
@@ -618,11 +618,11 @@ do {                                                      
                \
 } while (0)
 
 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
-#define __get_kernel_nofault(dst, src, type, err_label)                        
\
+#define arch_get_kernel_nofault(dst, src, type, err_label)             \
        __get_user_size(*((type *)(dst)), (__force type __user *)(src), \
                        sizeof(type), err_label)
 #else // !CONFIG_CC_HAS_ASM_GOTO_OUTPUT
-#define __get_kernel_nofault(dst, src, type, err_label)                        
\
+#define arch_get_kernel_nofault(dst, src, type, err_label)                     
\
 do {                                                                   \
        int __kr_err;                                                   \
                                                                        \
@@ -633,7 +633,7 @@ do {                                                        
                \
 } while (0)
 #endif // CONFIG_CC_HAS_ASM_GOTO_OUTPUT
 
-#define __put_kernel_nofault(dst, src, type, err_label)                        
\
+#define arch_put_kernel_nofault(dst, src, type, err_label)             \
        __put_user_size(*((type *)(src)), (__force type __user *)(dst), \
                        sizeof(type), err_label)
 


Reply via email to