]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
riscv/uaccess: Use unsafe wrappers for ASM GOTO
authorThomas Gleixner <tglx@linutronix.de>
Mon, 27 Oct 2025 08:43:50 +0000 (09:43 +0100)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 3 Nov 2025 14:26:10 +0000 (15:26 +0100)
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 <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Link: https://patch.msgid.link/20251027083745.419351819@linutronix.de
arch/riscv/include/asm/uaccess.h

index f5f4f7f85543f2a635b18e4bd1c6202b20e3b239..36bba6720c26ae963c9dc4571285fb28b0727239 100644 (file)
@@ -437,10 +437,10 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
                __clear_user(untagged_addr(to), n) : n;
 }
 
-#define __get_kernel_nofault(dst, src, type, err_label)                        \
+#define arch_get_kernel_nofault(dst, src, type, err_label)                     \
        __get_user_nocheck(*((type *)(dst)), (__force __user type *)(src), err_label)
 
-#define __put_kernel_nofault(dst, src, type, err_label)                        \
+#define arch_put_kernel_nofault(dst, src, type, err_label)                     \
        __put_user_nocheck(*((type *)(src)), (__force __user type *)(dst), err_label)
 
 static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
@@ -460,10 +460,10 @@ static inline void user_access_restore(unsigned long enabled) { }
  * We want the unsafe accessors to always be inlined and use
  * the error labels - thus the macro games.
  */
-#define unsafe_put_user(x, ptr, label)                                 \
+#define arch_unsafe_put_user(x, ptr, label)                            \
        __put_user_nocheck(x, (ptr), label)
 
-#define unsafe_get_user(x, ptr, label) do {                            \
+#define arch_unsafe_get_user(x, ptr, label)    do {                    \
        __inttype(*(ptr)) __gu_val;                                     \
        __get_user_nocheck(__gu_val, (ptr), label);                     \
        (x) = (__force __typeof__(*(ptr)))__gu_val;                     \