Re: [patch V5 04/12] powerpc/uaccess: Use unsafe wrappers for ASM GOTO
From: Christophe Leroy <hidden>
Date: 2025-11-04 06:50:11
Also in:
linux-arm-kernel, linux-fsdevel, linux-riscv, linux-s390, lkml
Le 27/10/2025 à 09:43, Thomas Gleixner a écrit :
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.
Confirmed on powerpc:
Before the patch
000001e8 <foo>:
1e8: 81 22 05 24 lwz r9,1316(r2)
1ec: 39 29 00 01 addi r9,r9,1
1f0: 91 22 05 24 stw r9,1316(r2)
1f4: 90 83 00 00 stw r4,0(r3)
1f8: 81 22 05 24 lwz r9,1316(r2)
1fc: 38 60 00 01 li r3,1
200: 39 29 ff ff addi r9,r9,-1
204: 91 22 05 24 stw r9,1316(r2)
208: 4e 80 00 20 blr
20c: 38 60 00 00 li r3,0
210: 4e 80 00 20 blr
00000000 <__ex_table>:
...
20: R_PPC_REL32 .text+0x1f4
24: R_PPC_REL32 .text+0x20c
After the patch
000001e8 <foo>:
1e8: 81 22 05 24 lwz r9,1316(r2)
1ec: 39 29 00 01 addi r9,r9,1
1f0: 91 22 05 24 stw r9,1316(r2)
1f4: 90 83 00 00 stw r4,0(r3)
1f8: 81 22 05 24 lwz r9,1316(r2)
1fc: 38 60 00 01 li r3,1
200: 39 29 ff ff addi r9,r9,-1
204: 91 22 05 24 stw r9,1316(r2)
208: 4e 80 00 20 blr
20c: 81 22 05 24 lwz r9,1316(r2)
210: 38 60 00 00 li r3,0
214: 39 29 ff ff addi r9,r9,-1
218: 91 22 05 24 stw r9,1316(r2)
21c: 4e 80 00 20 blr
00000000 <__ex_table>:
...
20: R_PPC_REL32 .text+0x1f4
24: R_PPC_REL32 .text+0x20c
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 <redacted> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Christophe Leroy <redacted> Cc: linuxppc-dev@lists.ozlabs.org
Reviewed-by: Christophe Leroy <redacted>
quoted hunk ↗ jump to hunk
--- arch/powerpc/include/asm/uaccess.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)--- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h@@ -451,7 +451,7 @@ user_write_access_begin(const void __use #define user_write_access_begin user_write_access_begin #define user_write_access_end prevent_current_write_to_user -#define unsafe_get_user(x, p, e) do { \ +#define arch_unsafe_get_user(x, p, e) do { \ __long_type(*(p)) __gu_val; \ __typeof__(*(p)) __user *__gu_addr = (p); \ \@@ -459,7 +459,7 @@ user_write_access_begin(const void __use (x) = (__typeof__(*(p)))__gu_val; \ } while (0) -#define unsafe_put_user(x, p, e) \ +#define arch_unsafe_put_user(x, p, e) \ __put_user_size_goto((__typeof__(*(p)))(x), (p), sizeof(*(p)), e) #define unsafe_copy_from_user(d, s, l, e) \@@ -504,11 +504,11 @@ do { \ unsafe_put_user(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e); \ } while (0) -#define __get_kernel_nofault(dst, src, type, err_label) \ +#define arch_get_kernel_nofault(dst, src, type, err_label) \ __get_user_size_goto(*((type *)(dst)), \ (__force type __user *)(src), sizeof(type), err_label) -#define __put_kernel_nofault(dst, src, type, err_label) \ +#define arch_put_kernel_nofault(dst, src, type, err_label) \ __put_user_size_goto(*((type *)(src)), \ (__force type __user *)(dst), sizeof(type), err_label)