[patch V3 00/12] uaccess: Provide and use scopes for user masked access

Thomas Gleixner posted 12 patches 2 months ago
arch/arm/include/asm/uaccess.h               |   26 ++
arch/powerpc/include/asm/uaccess.h           |    8
arch/riscv/include/asm/uaccess.h             |    8
arch/s390/include/asm/uaccess.h              |    4
arch/x86/include/asm/futex.h                 |   75 ++----
arch/x86/include/asm/uaccess.h               |   12 -
fs/select.c                                  |   12 -
include/linux/uaccess.h                      |  313 ++++++++++++++++++++++++++-
kernel/futex/futex.h                         |   37 ---
scripts/coccinelle/misc/scoped_uaccess.cocci |  108 +++++++++
10 files changed, 497 insertions(+), 106 deletions(-)
[patch V3 00/12] uaccess: Provide and use scopes for user masked access
Posted by Thomas Gleixner 2 months ago
This is a follow up on the V2 feedback:

   https://lore.kernel.org/20250916163004.674341701@linutronix.de

The main concern over the V2 implementation was the requirement to have
the code within the macro itself.

The main reason for that was the issue with ASM GOTO within a auto cleanup
scope. Clang refuses to build when the ASM GOTO label is outside of the
scope and GCC silently miscompiles the code and misses the cleanup.

After some back and forth discussion Linus suggested to put the local label
workaround into the user access functions themself.

The second reason for having this construct was to make the potential
modification of the pointer (when the architecture supports masking) scope
local, as that preserves the original pointer for the failure path.

Andrew thankfully pointed me to nested for() loops and after some head
scratching I managed to get all of it hidden in that construct.

So now the scoped access looks like this:

	scoped_masked_user_read_access(ptr, efault) {
	        // @ptr is aliased. An eventual mask modification is scope local
		unsafe_get_user(val, ptr, efault);
		...
	}
	return 0;
efault:
        // @ptr is unmodified
	do_stuff(ptr);
	return -EFAULT;


Changes vs. V2:

    - Fix the unsigned long long pointer issue in ARM get_user() -
      Christophe, Russell

    - Provide a generic workaround for the ASM GOTO issue and convert the
      affected architecture code over - Linus

    - Reimplement the scoped cleanup magic with nested for() loops - Andrew

    - Provide variants with size provided by the caller - Mathieu

    - Add get/put_user_masked() helpers for single read/write access

    - Fixup the usage in futex, x86. select

    - A clumsy attempt to implement a coccinelle checker which catches
      access mismatches, e.g. unsafe_put_user() inside a
      scoped_masked_user_read_access() region. That needs more thought and
      more coccinelle foo and is just there for discussion.

The series is based on v6.18-rc1 and also available from git:

    git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git uaccess/masked

Thanks,

	tglx
---
Thomas Gleixner (12):
      ARM: uaccess: Implement missing __get_user_asm_dword()
      uaccess: Provide ASM GOTO safe wrappers for unsafe_*_user()
      x86/uaccess: Use unsafe wrappers for ASM GOTO
      powerpc/uaccess: Use unsafe wrappers for ASM GOTO
      riscv/uaccess: Use unsafe wrappers for ASM GOTO
      s390/uaccess: Use unsafe wrappers for ASM GOTO
      uaccess: Provide scoped masked user access regions
      uaccess: Provide put/get_user_masked()
      coccinelle: misc: Add scoped_masked_$MODE_access() checker script
      futex: Convert to scoped masked user access
      x86/futex: Convert to scoped masked user access
      select: Convert to scoped masked user access

---
 arch/arm/include/asm/uaccess.h               |   26 ++
 arch/powerpc/include/asm/uaccess.h           |    8 
 arch/riscv/include/asm/uaccess.h             |    8 
 arch/s390/include/asm/uaccess.h              |    4 
 arch/x86/include/asm/futex.h                 |   75 ++----
 arch/x86/include/asm/uaccess.h               |   12 -
 fs/select.c                                  |   12 -
 include/linux/uaccess.h                      |  313 ++++++++++++++++++++++++++-
 kernel/futex/futex.h                         |   37 ---
 scripts/coccinelle/misc/scoped_uaccess.cocci |  108 +++++++++
 10 files changed, 497 insertions(+), 106 deletions(-)
Re: [patch V3 00/12] uaccess: Provide and use scopes for user masked access
Posted by Mathieu Desnoyers 2 months ago
On 2025-10-17 06:08, Thomas Gleixner wrote:
> This is a follow up on the V2 feedback:
> 
>     https://lore.kernel.org/20250916163004.674341701@linutronix.de
> 
> The main concern over the V2 implementation was the requirement to have
> the code within the macro itself.
> 
> The main reason for that was the issue with ASM GOTO within a auto cleanup
> scope. Clang refuses to build when the ASM GOTO label is outside of the
> scope and GCC silently miscompiles the code and misses the cleanup.
> 
> After some back and forth discussion Linus suggested to put the local label
> workaround into the user access functions themself.
> 
> The second reason for having this construct was to make the potential
> modification of the pointer (when the architecture supports masking) scope
> local, as that preserves the original pointer for the failure path.
> 
> Andrew thankfully pointed me to nested for() loops and after some head
> scratching I managed to get all of it hidden in that construct.
> 
> So now the scoped access looks like this:
> 
> 	scoped_masked_user_read_access(ptr, efault) {
> 	        // @ptr is aliased. An eventual mask modification is scope local
> 		unsafe_get_user(val, ptr, efault);
> 		...
> 	}

Now we're talking! It indeed looks much more like C now. I'll go review
the implementation.

Thanks,

Mathieu


> 	return 0;
> efault:
>          // @ptr is unmodified
> 	do_stuff(ptr);
> 	return -EFAULT;
> 
> 
> Changes vs. V2:
> 
>      - Fix the unsigned long long pointer issue in ARM get_user() -
>        Christophe, Russell
> 
>      - Provide a generic workaround for the ASM GOTO issue and convert the
>        affected architecture code over - Linus
> 
>      - Reimplement the scoped cleanup magic with nested for() loops - Andrew
> 
>      - Provide variants with size provided by the caller - Mathieu
> 
>      - Add get/put_user_masked() helpers for single read/write access
> 
>      - Fixup the usage in futex, x86. select
> 
>      - A clumsy attempt to implement a coccinelle checker which catches
>        access mismatches, e.g. unsafe_put_user() inside a
>        scoped_masked_user_read_access() region. That needs more thought and
>        more coccinelle foo and is just there for discussion.
> 
> The series is based on v6.18-rc1 and also available from git:
> 
>      git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git uaccess/masked
> 
> Thanks,
> 
> 	tglx
> ---
> Thomas Gleixner (12):
>        ARM: uaccess: Implement missing __get_user_asm_dword()
>        uaccess: Provide ASM GOTO safe wrappers for unsafe_*_user()
>        x86/uaccess: Use unsafe wrappers for ASM GOTO
>        powerpc/uaccess: Use unsafe wrappers for ASM GOTO
>        riscv/uaccess: Use unsafe wrappers for ASM GOTO
>        s390/uaccess: Use unsafe wrappers for ASM GOTO
>        uaccess: Provide scoped masked user access regions
>        uaccess: Provide put/get_user_masked()
>        coccinelle: misc: Add scoped_masked_$MODE_access() checker script
>        futex: Convert to scoped masked user access
>        x86/futex: Convert to scoped masked user access
>        select: Convert to scoped masked user access
> 
> ---
>   arch/arm/include/asm/uaccess.h               |   26 ++
>   arch/powerpc/include/asm/uaccess.h           |    8
>   arch/riscv/include/asm/uaccess.h             |    8
>   arch/s390/include/asm/uaccess.h              |    4
>   arch/x86/include/asm/futex.h                 |   75 ++----
>   arch/x86/include/asm/uaccess.h               |   12 -
>   fs/select.c                                  |   12 -
>   include/linux/uaccess.h                      |  313 ++++++++++++++++++++++++++-
>   kernel/futex/futex.h                         |   37 ---
>   scripts/coccinelle/misc/scoped_uaccess.cocci |  108 +++++++++
>   10 files changed, 497 insertions(+), 106 deletions(-)


-- 
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
Re: [patch V3 00/12] uaccess: Provide and use scopes for user masked access
Posted by Peter Zijlstra 2 months ago
On Fri, Oct 17, 2025 at 12:08:54PM +0200, Thomas Gleixner wrote:

> After some back and forth discussion Linus suggested to put the local label
> workaround into the user access functions themself.

> Andrew thankfully pointed me to nested for() loops and after some head
> scratching I managed to get all of it hidden in that construct.

These two hacks are awesome and made my day; thanks!

> Thomas Gleixner (12):
>       ARM: uaccess: Implement missing __get_user_asm_dword()
>       uaccess: Provide ASM GOTO safe wrappers for unsafe_*_user()
>       x86/uaccess: Use unsafe wrappers for ASM GOTO
>       powerpc/uaccess: Use unsafe wrappers for ASM GOTO
>       riscv/uaccess: Use unsafe wrappers for ASM GOTO
>       s390/uaccess: Use unsafe wrappers for ASM GOTO
>       uaccess: Provide scoped masked user access regions
>       uaccess: Provide put/get_user_masked()
>       futex: Convert to scoped masked user access
>       x86/futex: Convert to scoped masked user access

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>

>       select: Convert to scoped masked user access

Basically okay on this one too, except see the comment.

>       coccinelle: misc: Add scoped_masked_$MODE_access() checker script

And that's just pure magic, I can't seem to get me head around
coccinelle syntax.
Re: [patch V3 00/12] uaccess: Provide and use scopes for user masked access
Posted by Andrew Cooper 2 months ago
On 17/10/2025 11:37 am, Peter Zijlstra wrote:
> On Fri, Oct 17, 2025 at 12:08:54PM +0200, Thomas Gleixner wrote:
>> Andrew thankfully pointed me to nested for() loops and after some head
>> scratching I managed to get all of it hidden in that construct.
> These two hacks are awesome and made my day; thanks!

It's a new four loop paradigm, brought to you by a silly restriction in C99.

~Andrew