* [PATCH v2 0/5] uaccess: Updates to scoped_user_access()
@ 2026-03-02 13:27 david.laight.linux
2026-03-02 13:27 ` [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const' david.laight.linux
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: david.laight.linux @ 2026-03-02 13:27 UTC (permalink / raw)
To: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, David Laight,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
From: David Laight <david.laight.linux@gmail.com>
Converting kernel/signal.c to use scoped_user_access() had compilation
warnings because some of the pointers are 'pointer to const'.
This is fixed in patch 1.
The same problem has been found compiling arch/powerpc/lib/checksum_wrappers.c
For v2 I've changed the code to use 'auto' and replaced the over-complex
CLASS definition (and its for loop) with a much simpler __cleanup() function
on the second loop.
Patches 2 and 3 factor out the 'autoterminating nested for loops'.
I'm sure there'll be a 'bikeshed' discussion about the names.
Patch 4 stops warnings from -Wshadow (enabled by W=2).
I did think about making the _diag_xxx conditional on a W=2 build,
but since the pre-processor just emits #pragma lines and they are
smaller that the for() loop it doesn't seem worth while.
Patch 5 is the change to signal.c that prompted patch 1.
The generated code looks fine, but I've not tested it.
Most of the changes are to 'compat' code - so are probably not
usually performance critical.
IIRC the non-compat code uses copy_to/from_user() for the structures
so is probably slower than the compat code's member by member copy.
David Laight (5):
uaccess: Fix scoped_user_read_access() for 'pointer to const'
compiler.h: Add generic support for 'autoterminating nested for()
loops'
uaccess.h: Use with() and and_with() in __scoped_user_access()
uaccess: Disable -Wshadow in __scoped_user_access()
signal: Use scoped_user_access() instead of __put/get_user()
include/linux/compiler.h | 26 +++++++++++++++
include/linux/uaccess.h | 51 ++++++++++------------------
kernel/signal.c | 72 +++++++++++++++++++++++-----------------
3 files changed, 86 insertions(+), 63 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const'
2026-03-02 13:27 [PATCH v2 0/5] uaccess: Updates to scoped_user_access() david.laight.linux
@ 2026-03-02 13:27 ` david.laight.linux
2026-03-02 14:59 ` Christophe Leroy (CS GROUP)
2026-03-02 13:27 ` [PATCH v2 2/5] compiler.h: Add generic support for 'autoterminating nested for() loops' david.laight.linux
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: david.laight.linux @ 2026-03-02 13:27 UTC (permalink / raw)
To: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, David Laight,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
From: David Laight <david.laight.linux@gmail.com>
If a 'const struct foo __user *ptr' is used for the address passed
to scoped_user_read_access() then you get a warning/error
uaccess.h:691:1: error: initialization discards 'const' qualifier
from pointer target type [-Werror=discarded-qualifiers]
for the
void __user *_tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)
assignment.
Fix by using 'auto' for both _tmpptr and the redeclaration of uptr.
Replace the CLASS() with explicit __cleanup() functions on uptr.
Fixes: e497310b4ffb "(uaccess: Provide scoped user access regions)"
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/uaccess.h | 54 +++++++++++++++--------------------------
1 file changed, 20 insertions(+), 34 deletions(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 1f3804245c06..809e4f7dfdbd 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -647,36 +647,22 @@ static inline void user_access_restore(unsigned long flags) { }
/* Define RW variant so the below _mode macro expansion works */
#define masked_user_rw_access_begin(u) masked_user_access_begin(u)
#define user_rw_access_begin(u, s) user_access_begin(u, s)
-#define user_rw_access_end() user_access_end()
/* Scoped user access */
-#define USER_ACCESS_GUARD(_mode) \
-static __always_inline void __user * \
-class_user_##_mode##_begin(void __user *ptr) \
-{ \
- return ptr; \
-} \
- \
-static __always_inline void \
-class_user_##_mode##_end(void __user *ptr) \
-{ \
- user_##_mode##_access_end(); \
-} \
- \
-DEFINE_CLASS(user_ ##_mode## _access, void __user *, \
- class_user_##_mode##_end(_T), \
- class_user_##_mode##_begin(ptr), void __user *ptr) \
- \
-static __always_inline class_user_##_mode##_access_t \
-class_user_##_mode##_access_ptr(void __user *scope) \
-{ \
- return scope; \
-}
-USER_ACCESS_GUARD(read)
-USER_ACCESS_GUARD(write)
-USER_ACCESS_GUARD(rw)
-#undef USER_ACCESS_GUARD
+/* Cleanup wrapper functions */
+static __always_inline void __scoped_user_read_access_end(const void *p)
+{
+ user_read_access_end();
+};
+static __always_inline void __scoped_user_write_access_end(const void *p)
+{
+ user_write_access_end();
+};
+static __always_inline void __scoped_user_rw_access_end(const void *p)
+{
+ user_access_end();
+};
/**
* __scoped_user_access_begin - Start a scoped user access
@@ -750,13 +736,13 @@ USER_ACCESS_GUARD(rw)
*
* Don't use directly. Use scoped_masked_user_$MODE_access() instead.
*/
-#define __scoped_user_access(mode, uptr, size, elbl) \
-for (bool done = false; !done; done = true) \
- for (void __user *_tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl); \
- !done; done = true) \
- for (CLASS(user_##mode##_access, scope)(_tmpptr); !done; done = true) \
- /* Force modified pointer usage within the scope */ \
- for (const typeof(uptr) uptr = _tmpptr; !done; done = true)
+#define __scoped_user_access(mode, uptr, size, elbl) \
+for (bool done = false; !done; done = true) \
+ for (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl); \
+ !done; done = true) \
+ /* Force modified pointer usage within the scope */ \
+ for (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = \
+ _tmpptr; !done; done = true)
/**
* scoped_user_read_access_size - Start a scoped user read access with given size
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 2/5] compiler.h: Add generic support for 'autoterminating nested for() loops'
2026-03-02 13:27 [PATCH v2 0/5] uaccess: Updates to scoped_user_access() david.laight.linux
2026-03-02 13:27 ` [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const' david.laight.linux
@ 2026-03-02 13:27 ` david.laight.linux
2026-03-02 13:27 ` [PATCH v2 3/5] uaccess.h: Use with() and and_with() in __scoped_user_access() david.laight.linux
` (2 subsequent siblings)
4 siblings, 0 replies; 14+ messages in thread
From: david.laight.linux @ 2026-03-02 13:27 UTC (permalink / raw)
To: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, David Laight,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
From: David Laight <david.laight.linux@gmail.com>
Autoterminating nested for() loops can be used inside #defines to
declare variables that are scoped to the statement that follows.
These are used by __scoped_user_access() but may have other uses
and the gory details are best separated from the use.
Using 'with (declaration)' and 'and_with (declaration)' seems to
read reasonably well and doesn't seem to collide with any existing
code.
As an example the scoped user access definition becomes:
with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
/* Force modified pointer usage within the scope */ \
and_with (const auto uptr __cleanup(...) = _tmpptr)
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/compiler.h | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index af16624b29fd..1098a91b5591 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -369,6 +369,32 @@ static inline void *offset_to_ptr(const int *off)
*/
#define prevent_tail_call_optimization() mb()
+/*
+ * Sometimes a #define needs to declare a variable that is scoped
+ * to the statement that follows without having mismatched {}.
+ * with (int x = expression) {
+ * statements
+ * }
+ * is the same as:
+ * {
+ * int x = expression;
+ * statements
+ * }
+ * but lets it all be hidden from the call site, eg:
+ * frobnicate(x, args) {
+ * statements
+ * }
+ * Only a single variable can be defined, and_with() allows extra ones
+ * without adding an additional outer loop.
+ *
+ * The controlled scope can be terminated using return, break, continue or goto.
+ */
+#define with(declaration) \
+ for (bool _with_done = false; !_with_done; _with_done = true) \
+ and_with (declaration)
+#define and_with(declaration) \
+ for (declaration; !_with_done; _with_done = true)
+
#include <asm/rwonce.h>
#endif /* __LINUX_COMPILER_H */
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 3/5] uaccess.h: Use with() and and_with() in __scoped_user_access()
2026-03-02 13:27 [PATCH v2 0/5] uaccess: Updates to scoped_user_access() david.laight.linux
2026-03-02 13:27 ` [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const' david.laight.linux
2026-03-02 13:27 ` [PATCH v2 2/5] compiler.h: Add generic support for 'autoterminating nested for() loops' david.laight.linux
@ 2026-03-02 13:27 ` david.laight.linux
2026-03-02 13:27 ` [PATCH v2 4/5] uaccess: Disable -Wshadow " david.laight.linux
2026-03-02 13:27 ` [PATCH v2 next 5/5] signal: Use scoped_user_access() instead of __put/get_user() david.laight.linux
4 siblings, 0 replies; 14+ messages in thread
From: david.laight.linux @ 2026-03-02 13:27 UTC (permalink / raw)
To: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, David Laight,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
From: David Laight <david.laight.linux@gmail.com>
Wrappers for autoterminating nested for() loops have been added to
compiler.h, use them to hide the gory details.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/uaccess.h | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 809e4f7dfdbd..64bc2492eb99 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -736,13 +736,10 @@ static __always_inline void __scoped_user_rw_access_end(const void *p)
*
* Don't use directly. Use scoped_masked_user_$MODE_access() instead.
*/
-#define __scoped_user_access(mode, uptr, size, elbl) \
-for (bool done = false; !done; done = true) \
- for (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl); \
- !done; done = true) \
- /* Force modified pointer usage within the scope */ \
- for (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = \
- _tmpptr; !done; done = true)
+#define __scoped_user_access(mode, uptr, size, elbl) \
+ with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
+ /* Force modified pointer usage within the scope */ \
+ and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr)
/**
* scoped_user_read_access_size - Start a scoped user read access with given size
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 4/5] uaccess: Disable -Wshadow in __scoped_user_access()
2026-03-02 13:27 [PATCH v2 0/5] uaccess: Updates to scoped_user_access() david.laight.linux
` (2 preceding siblings ...)
2026-03-02 13:27 ` [PATCH v2 3/5] uaccess.h: Use with() and and_with() in __scoped_user_access() david.laight.linux
@ 2026-03-02 13:27 ` david.laight.linux
2026-03-02 15:00 ` Christophe Leroy (CS GROUP)
` (2 more replies)
2026-03-02 13:27 ` [PATCH v2 next 5/5] signal: Use scoped_user_access() instead of __put/get_user() david.laight.linux
4 siblings, 3 replies; 14+ messages in thread
From: david.laight.linux @ 2026-03-02 13:27 UTC (permalink / raw)
To: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, David Laight,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
From: David Laight <david.laight.linux@gmail.com>
-Wshadow is enabled by W=2 builds and __scoped_user_access() quite
deliberately creates a 'const' shadow of the 'user' address that
references a 'guard page' when the application passes a kernel pointer.
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
include/linux/uaccess.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 64bc2492eb99..445391ec5a6d 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -739,7 +739,9 @@ static __always_inline void __scoped_user_rw_access_end(const void *p)
#define __scoped_user_access(mode, uptr, size, elbl) \
with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
/* Force modified pointer usage within the scope */ \
- and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr)
+ __diag_push() __diag_ignore_all("-Wshadow", "uptr is readonly copy") \
+ and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
+ __diag_pop()
/**
* scoped_user_read_access_size - Start a scoped user read access with given size
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 next 5/5] signal: Use scoped_user_access() instead of __put/get_user()
2026-03-02 13:27 [PATCH v2 0/5] uaccess: Updates to scoped_user_access() david.laight.linux
` (3 preceding siblings ...)
2026-03-02 13:27 ` [PATCH v2 4/5] uaccess: Disable -Wshadow " david.laight.linux
@ 2026-03-02 13:27 ` david.laight.linux
2026-03-02 16:07 ` Christophe Leroy (CS GROUP)
4 siblings, 1 reply; 14+ messages in thread
From: david.laight.linux @ 2026-03-02 13:27 UTC (permalink / raw)
To: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, David Laight,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
From: David Laight <david.laight.linux@gmail.com>
Mechanically change the access_ok() and __get/put_user() to use
scoped_user_read/write_access() and unsafe_get/put_user().
This generates better code with fewer STAC/CLAC pairs.
It also ensures that access_ok() is called near the user accesses.
I failed to find the one for __save_altstack().
Looking at the change, perhaps there should be aliases:
#define scoped_put_user unsafe_put_user
#define scoped_get_user unsafe_get_user
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
kernel/signal.c | 72 ++++++++++++++++++++++++++++---------------------
1 file changed, 42 insertions(+), 30 deletions(-)
diff --git a/kernel/signal.c b/kernel/signal.c
index d65d0fe24bfb..fca257398cbc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -4469,10 +4469,16 @@ int restore_altstack(const stack_t __user *uss)
int __save_altstack(stack_t __user *uss, unsigned long sp)
{
struct task_struct *t = current;
- int err = __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) |
- __put_user(t->sas_ss_flags, &uss->ss_flags) |
- __put_user(t->sas_ss_size, &uss->ss_size);
- return err;
+
+ scoped_user_write_access(uss, Efault) {
+ unsafe_put_user((void __user *)t->sas_ss_sp, &uss->ss_sp, Efault);
+ unsafe_put_user(t->sas_ss_flags, &uss->ss_flags, Efault);
+ unsafe_put_user(t->sas_ss_size, &uss->ss_size, Efault);
+ }
+ return 0;
+
+Efault:
+ return -EFAULT;
}
#ifdef CONFIG_COMPAT
@@ -4705,12 +4711,12 @@ SYSCALL_DEFINE3(sigaction, int, sig,
if (act) {
old_sigset_t mask;
- if (!access_ok(act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
+ scoped_user_read_access(act, Efault) {
+ unsafe_get_user(new_ka.sa.sa_handler, &act->sa_handler, Efault);
+ unsafe_get_user(new_ka.sa.sa_restorer, &act->sa_restorer, Efault);
+ unsafe_get_user(new_ka.sa.sa_flags, &act->sa_flags, Efault);
+ unsafe_get_user(mask, &act->sa_mask, Efault);
+ }
#ifdef __ARCH_HAS_KA_RESTORER
new_ka.ka_restorer = NULL;
#endif
@@ -4720,15 +4726,18 @@ SYSCALL_DEFINE3(sigaction, int, sig,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (!access_ok(oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
+ scoped_user_write_access(oact, Efault) {
+ unsafe_put_user(old_ka.sa.sa_handler, &oact->sa_handler, Efault);
+ unsafe_put_user(old_ka.sa.sa_restorer, &oact->sa_restorer, Efault);
+ unsafe_put_user(old_ka.sa.sa_flags, &oact->sa_flags, Efault);
+ unsafe_put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask, Efault);
+ }
}
return ret;
+
+Efault:
+ return -EFAULT;
}
#endif
#ifdef CONFIG_COMPAT_OLD_SIGACTION
@@ -4742,12 +4751,12 @@ COMPAT_SYSCALL_DEFINE3(sigaction, int, sig,
compat_uptr_t handler, restorer;
if (act) {
- if (!access_ok(act, sizeof(*act)) ||
- __get_user(handler, &act->sa_handler) ||
- __get_user(restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
+ scoped_user_read_access(act, Efault) {
+ unsafe_get_user(handler, &act->sa_handler, Efault);
+ unsafe_get_user(restorer, &act->sa_restorer, Efault);
+ unsafe_get_user(new_ka.sa.sa_flags, &act->sa_flags, Efault);
+ unsafe_get_user(mask, &act->sa_mask, Efault);
+ }
#ifdef __ARCH_HAS_KA_RESTORER
new_ka.ka_restorer = NULL;
@@ -4760,16 +4769,19 @@ COMPAT_SYSCALL_DEFINE3(sigaction, int, sig,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (!access_ok(oact, sizeof(*oact)) ||
- __put_user(ptr_to_compat(old_ka.sa.sa_handler),
- &oact->sa_handler) ||
- __put_user(ptr_to_compat(old_ka.sa.sa_restorer),
- &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
+ scoped_user_write_access(oact, Efault) {
+ unsafe_put_user(ptr_to_compat(old_ka.sa.sa_handler),
+ &oact->sa_handler, Efault);
+ unsafe_put_user(ptr_to_compat(old_ka.sa.sa_restorer),
+ &oact->sa_restorer, Efault);
+ unsafe_put_user(old_ka.sa.sa_flags, &oact->sa_flags, Efault);
+ unsafe_put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask, Efault);
+ }
}
return ret;
+
+Efault:
+ return -EFAULT;
}
#endif
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const'
2026-03-02 13:27 ` [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const' david.laight.linux
@ 2026-03-02 14:59 ` Christophe Leroy (CS GROUP)
2026-03-02 17:26 ` Linus Torvalds
0 siblings, 1 reply; 14+ messages in thread
From: Christophe Leroy (CS GROUP) @ 2026-03-02 14:59 UTC (permalink / raw)
To: david.laight.linux, Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Darren Hart, Davidlohr Bueso, Heiko Carstens, Jan Kara,
Julia Lawall, Linus Torvalds, linux-arm-kernel, linux-fsdevel,
linuxppc-dev, linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
Le 02/03/2026 à 14:27, david.laight.linux@gmail.com a écrit :
> From: David Laight <david.laight.linux@gmail.com>
>
> If a 'const struct foo __user *ptr' is used for the address passed
> to scoped_user_read_access() then you get a warning/error
> uaccess.h:691:1: error: initialization discards 'const' qualifier
> from pointer target type [-Werror=discarded-qualifiers]
> for the
> void __user *_tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)
> assignment.
>
> Fix by using 'auto' for both _tmpptr and the redeclaration of uptr.
> Replace the CLASS() with explicit __cleanup() functions on uptr.
>
> Fixes: e497310b4ffb "(uaccess: Provide scoped user access regions)"
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Tested-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Can we get this fix merged in 7.0-rc3 so that we can start building 7.1
on top of it ?
Thanks
Christophe
> ---
> include/linux/uaccess.h | 54 +++++++++++++++--------------------------
> 1 file changed, 20 insertions(+), 34 deletions(-)
>
> diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
> index 1f3804245c06..809e4f7dfdbd 100644
> --- a/include/linux/uaccess.h
> +++ b/include/linux/uaccess.h
> @@ -647,36 +647,22 @@ static inline void user_access_restore(unsigned long flags) { }
> /* Define RW variant so the below _mode macro expansion works */
> #define masked_user_rw_access_begin(u) masked_user_access_begin(u)
> #define user_rw_access_begin(u, s) user_access_begin(u, s)
> -#define user_rw_access_end() user_access_end()
>
> /* Scoped user access */
> -#define USER_ACCESS_GUARD(_mode) \
> -static __always_inline void __user * \
> -class_user_##_mode##_begin(void __user *ptr) \
> -{ \
> - return ptr; \
> -} \
> - \
> -static __always_inline void \
> -class_user_##_mode##_end(void __user *ptr) \
> -{ \
> - user_##_mode##_access_end(); \
> -} \
> - \
> -DEFINE_CLASS(user_ ##_mode## _access, void __user *, \
> - class_user_##_mode##_end(_T), \
> - class_user_##_mode##_begin(ptr), void __user *ptr) \
> - \
> -static __always_inline class_user_##_mode##_access_t \
> -class_user_##_mode##_access_ptr(void __user *scope) \
> -{ \
> - return scope; \
> -}
>
> -USER_ACCESS_GUARD(read)
> -USER_ACCESS_GUARD(write)
> -USER_ACCESS_GUARD(rw)
> -#undef USER_ACCESS_GUARD
> +/* Cleanup wrapper functions */
> +static __always_inline void __scoped_user_read_access_end(const void *p)
> +{
> + user_read_access_end();
> +};
> +static __always_inline void __scoped_user_write_access_end(const void *p)
> +{
> + user_write_access_end();
> +};
> +static __always_inline void __scoped_user_rw_access_end(const void *p)
> +{
> + user_access_end();
> +};
>
> /**
> * __scoped_user_access_begin - Start a scoped user access
> @@ -750,13 +736,13 @@ USER_ACCESS_GUARD(rw)
> *
> * Don't use directly. Use scoped_masked_user_$MODE_access() instead.
> */
> -#define __scoped_user_access(mode, uptr, size, elbl) \
> -for (bool done = false; !done; done = true) \
> - for (void __user *_tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl); \
> - !done; done = true) \
> - for (CLASS(user_##mode##_access, scope)(_tmpptr); !done; done = true) \
> - /* Force modified pointer usage within the scope */ \
> - for (const typeof(uptr) uptr = _tmpptr; !done; done = true)
> +#define __scoped_user_access(mode, uptr, size, elbl) \
> +for (bool done = false; !done; done = true) \
> + for (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl); \
> + !done; done = true) \
> + /* Force modified pointer usage within the scope */ \
> + for (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = \
> + _tmpptr; !done; done = true)
>
> /**
> * scoped_user_read_access_size - Start a scoped user read access with given size
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] uaccess: Disable -Wshadow in __scoped_user_access()
2026-03-02 13:27 ` [PATCH v2 4/5] uaccess: Disable -Wshadow " david.laight.linux
@ 2026-03-02 15:00 ` Christophe Leroy (CS GROUP)
2026-03-03 9:12 ` David Laight
2026-03-02 17:17 ` Linus Torvalds
2026-03-05 8:10 ` kernel test robot
2 siblings, 1 reply; 14+ messages in thread
From: Christophe Leroy (CS GROUP) @ 2026-03-02 15:00 UTC (permalink / raw)
To: david.laight.linux, Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Darren Hart,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
Le 02/03/2026 à 14:27, david.laight.linux@gmail.com a écrit :
> From: David Laight <david.laight.linux@gmail.com>
>
> -Wshadow is enabled by W=2 builds and __scoped_user_access() quite
> deliberately creates a 'const' shadow of the 'user' address that
> references a 'guard page' when the application passes a kernel pointer.
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
There is a problem with this patch:
DESCEND objtool
INSTALL libsubcmd_headers
CALL scripts/checksyscalls.sh
CC kernel/futex/core.o
In file included from ./include/asm-generic/div64.h:27,
from ./arch/powerpc/include/generated/asm/div64.h:1,
from ./include/linux/math.h:6,
from ./include/linux/math64.h:6,
from ./include/linux/time.h:6,
from ./include/linux/compat.h:10,
from kernel/futex/core.c:34:
kernel/futex/futex.h: In function 'futex_get_value_locked':
./include/linux/uaccess.h:740:20: warning: unused variable '_tmpptr'
[-Wunused-variable]
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~~~~
./include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
./include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
./include/linux/compiler.h:396:9: warning: this 'for' clause does not
guard... [-Wmisleading-indentation]
396 | for (declaration; !_with_done; _with_done = true)
| ^~~
./include/linux/compiler.h:394:17: note: in expansion of macro 'and_with'
394 | and_with (declaration)
| ^~~~~~~~
./include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
In file included from ././include/linux/compiler_types.h:173,
from <command-line>:
./include/linux/compiler-gcc.h:118:33: note: ...this statement, but the
latter is misleadingly indented as if it were guarded by the 'for'
118 | #define __diag(s) _Pragma(__diag_str(GCC
diagnostic s))
| ^~~~~~~
./include/linux/compiler-gcc.h:129:9: note: in expansion of macro '__diag'
129 | __diag(__diag_GCC_ignore option)
| ^~~~~~
./include/linux/uaccess.h:742:31: note: in expansion of macro
'__diag_ignore_all'
742 | __diag_push() __diag_ignore_all("-Wshadow",
"uptr is readonly copy") \
| ^~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
In file included from ./include/asm-generic/div64.h:27,
from ./arch/powerpc/include/generated/asm/div64.h:1,
from ./include/linux/math.h:6,
from ./include/linux/math64.h:6,
from ./include/linux/time.h:6,
from ./include/linux/compat.h:10,
from kernel/futex/core.c:34:
./include/linux/uaccess.h:743:90: error: '_tmpptr' undeclared (first use
in this function)
743 | and_with (const auto uptr
__cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
|
^~~~~~~
./include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
./include/linux/uaccess.h:743:90: note: each undeclared identifier is
reported only once for each function it appears in
743 | and_with (const auto uptr
__cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
|
^~~~~~~
./include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
./include/linux/compiler.h:396:28: error: '_with_done' undeclared (first
use in this function)
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~
./include/linux/uaccess.h:743:17: note: in expansion of macro 'and_with'
743 | and_with (const auto uptr
__cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
kernel/futex/core.c: In function 'get_futex_key':
./include/linux/uaccess.h:740:20: warning: unused variable '_tmpptr'
[-Wunused-variable]
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~~~~
./include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
./include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
./include/linux/compiler.h:396:9: warning: this 'for' clause does not
guard... [-Wmisleading-indentation]
396 | for (declaration; !_with_done; _with_done = true)
| ^~~
./include/linux/compiler.h:394:17: note: in expansion of macro 'and_with'
394 | and_with (declaration)
| ^~~~~~~~
./include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
In file included from ././include/linux/compiler_types.h:173,
from <command-line>:
./include/linux/compiler-gcc.h:118:33: note: ...this statement, but the
latter is misleadingly indented as if it were guarded by the 'for'
118 | #define __diag(s) _Pragma(__diag_str(GCC
diagnostic s))
| ^~~~~~~
./include/linux/compiler-gcc.h:129:9: note: in expansion of macro '__diag'
129 | __diag(__diag_GCC_ignore option)
| ^~~~~~
./include/linux/uaccess.h:742:31: note: in expansion of macro
'__diag_ignore_all'
742 | __diag_push() __diag_ignore_all("-Wshadow",
"uptr is readonly copy") \
| ^~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
In file included from ./include/asm-generic/div64.h:27,
from ./arch/powerpc/include/generated/asm/div64.h:1,
from ./include/linux/math.h:6,
from ./include/linux/math64.h:6,
from ./include/linux/time.h:6,
from ./include/linux/compat.h:10,
from kernel/futex/core.c:34:
./include/linux/uaccess.h:743:90: error: '_tmpptr' undeclared (first use
in this function)
743 | and_with (const auto uptr
__cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
|
^~~~~~~
./include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
./include/linux/compiler.h:396:28: error: '_with_done' undeclared (first
use in this function)
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~
./include/linux/uaccess.h:743:17: note: in expansion of macro 'and_with'
743 | and_with (const auto uptr
__cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~~
./include/linux/uaccess.h:755:9: note: in expansion of macro
'__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:767:9: note: in expansion of macro
'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:831:9: note: in expansion of macro
'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
./include/linux/uaccess.h:740:20: warning: unused variable '_tmpptr'
[-Wunused-variable]
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~~~~
./include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
./include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~
./include/linux/uaccess.h:778:9: note: in expansion of macro
'__scoped_user_access'
778 | __scoped_user_access(write, udst, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:790:9: note: in expansion of macro
'scoped_user_write_access_size'
790 | scoped_user_write_access_size(udst, sizeof(*(udst)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:856:9: note: in expansion of macro
'scoped_user_write_access'
856 | scoped_user_write_access(_tmpdst, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:604:37: note: in expansion of macro 'put_user_inline'
604 | if (node_updated && put_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
./include/linux/compiler.h:396:9: warning: this 'for' clause does not
guard... [-Wmisleading-indentation]
396 | for (declaration; !_with_done; _with_done = true)
| ^~~
./include/linux/compiler.h:394:17: note: in expansion of macro 'and_with'
394 | and_with (declaration)
| ^~~~~~~~
./include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode,
uptr, size, elbl)) \
| ^~~~
./include/linux/uaccess.h:778:9: note: in expansion of macro
'__scoped_user_access'
778 | __scoped_user_access(write, udst, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:790:9: note: in expansion of macro
'scoped_user_write_access_size'
790 | scoped_user_write_access_size(udst, sizeof(*(udst)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:856:9: note: in expansion of macro
'scoped_user_write_access'
856 | scoped_user_write_access(_tmpdst, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:604:37: note: in expansion of macro 'put_user_inline'
604 | if (node_updated && put_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
In file included from ././include/linux/compiler_types.h:173,
from <command-line>:
./include/linux/compiler-gcc.h:118:33: note: ...this statement, but the
latter is misleadingly indented as if it were guarded by the 'for'
118 | #define __diag(s) _Pragma(__diag_str(GCC
diagnostic s))
| ^~~~~~~
./include/linux/compiler-gcc.h:129:9: note: in expansion of macro '__diag'
129 | __diag(__diag_GCC_ignore option)
| ^~~~~~
./include/linux/uaccess.h:742:31: note: in expansion of macro
'__diag_ignore_all'
742 | __diag_push() __diag_ignore_all("-Wshadow",
"uptr is readonly copy") \
| ^~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:778:9: note: in expansion of macro
'__scoped_user_access'
778 | __scoped_user_access(write, udst, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:790:9: note: in expansion of macro
'scoped_user_write_access_size'
790 | scoped_user_write_access_size(udst, sizeof(*(udst)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/uaccess.h:856:9: note: in expansion of macro
'scoped_user_write_access'
856 | scoped_user_write_access(_tmpdst, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:604:37: note: in expansion of macro 'put_user_inline'
604 | if (node_updated && put_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
make[4]: *** [scripts/Makefile.build:289: kernel/futex/core.o] Error 1
make[3]: *** [scripts/Makefile.build:546: kernel/futex] Error 2
make[2]: *** [scripts/Makefile.build:546: kernel] Error 2
make[1]: *** [/home/chleroy/linux-powerpc/Makefile:2101: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2
> ---
> include/linux/uaccess.h | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
> index 64bc2492eb99..445391ec5a6d 100644
> --- a/include/linux/uaccess.h
> +++ b/include/linux/uaccess.h
> @@ -739,7 +739,9 @@ static __always_inline void __scoped_user_rw_access_end(const void *p)
> #define __scoped_user_access(mode, uptr, size, elbl) \
> with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
> /* Force modified pointer usage within the scope */ \
> - and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr)
> + __diag_push() __diag_ignore_all("-Wshadow", "uptr is readonly copy") \
> + and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
> + __diag_pop()
>
> /**
> * scoped_user_read_access_size - Start a scoped user read access with given size
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 next 5/5] signal: Use scoped_user_access() instead of __put/get_user()
2026-03-02 13:27 ` [PATCH v2 next 5/5] signal: Use scoped_user_access() instead of __put/get_user() david.laight.linux
@ 2026-03-02 16:07 ` Christophe Leroy (CS GROUP)
0 siblings, 0 replies; 14+ messages in thread
From: Christophe Leroy (CS GROUP) @ 2026-03-02 16:07 UTC (permalink / raw)
To: david.laight.linux, Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Darren Hart, Davidlohr Bueso, Heiko Carstens, Jan Kara,
Julia Lawall, Linus Torvalds, linux-arm-kernel, linux-fsdevel,
linuxppc-dev, linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
Le 02/03/2026 à 14:27, david.laight.linux@gmail.com a écrit :
> From: David Laight <david.laight.linux@gmail.com>
>
> Mechanically change the access_ok() and __get/put_user() to use
> scoped_user_read/write_access() and unsafe_get/put_user().
>
> This generates better code with fewer STAC/CLAC pairs.
>
> It also ensures that access_ok() is called near the user accesses.
> I failed to find the one for __save_altstack().
On arm64 it's done in get_sigframe() it seems.
>
> Looking at the change, perhaps there should be aliases:
> #define scoped_put_user unsafe_put_user
> #define scoped_get_user unsafe_get_user
Might be confusing to have two macros doing exactly the same thing.
And the churn might be unnecessary on some code that already widely use
unsafe_xxx macros and that we want to convert to scoped user access,
like for instance arch/powerpc/kernel/signal_32.c
Christophe
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] uaccess: Disable -Wshadow in __scoped_user_access()
2026-03-02 13:27 ` [PATCH v2 4/5] uaccess: Disable -Wshadow " david.laight.linux
2026-03-02 15:00 ` Christophe Leroy (CS GROUP)
@ 2026-03-02 17:17 ` Linus Torvalds
2026-03-05 8:10 ` kernel test robot
2 siblings, 0 replies; 14+ messages in thread
From: Linus Torvalds @ 2026-03-02 17:17 UTC (permalink / raw)
To: david.laight.linux
Cc: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, Davidlohr Bueso,
Heiko Carstens, Jan Kara, Julia Lawall, linux-arm-kernel,
linux-fsdevel, linuxppc-dev, linux-riscv, linux-s390, LKML,
Madhavan Srinivasan, Mathieu Desnoyers, Michael Ellerman,
Nicholas Piggin, Nicolas Palix, Palmer Dabbelt, Paul Walmsley,
Peter Zijlstra, Russell King, Sven Schnelle, Thomas Gleixner, x86,
Kees Cook, akpm
On Mon, 2 Mar 2026 at 05:28, <david.laight.linux@gmail.com> wrote:
>
> From: David Laight <david.laight.linux@gmail.com>
>
> -Wshadow is enabled by W=2 builds and __scoped_user_access() quite
> deliberately creates a 'const' shadow of the 'user' address that
> references a 'guard page' when the application passes a kernel pointer.
This is too ugly to live.
There is no way that we should make an already unreadable macro even
worse just because somebody - incorrectly - thinks that W=2 matters.
No - what matters a whole lot more is keeping the kernel sources
readable (well, at least as readable as is possible).
Because W=2 is one of those "you get what you deserve" things.
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const'
2026-03-02 14:59 ` Christophe Leroy (CS GROUP)
@ 2026-03-02 17:26 ` Linus Torvalds
2026-03-02 18:55 ` David Laight
0 siblings, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2026-03-02 17:26 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: david.laight.linux, Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Darren Hart, Davidlohr Bueso, Heiko Carstens, Jan Kara,
Julia Lawall, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
On Mon, 2 Mar 2026 at 06:59, Christophe Leroy (CS GROUP)
<chleroy@kernel.org> wrote:
>
> Can we get this fix merged in 7.0-rc3 so that we can start building 7.1
> on top of it ?
Applied this first patch. I'm not so convinced about the others in the
series, although people can always try to argue for them..
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const'
2026-03-02 17:26 ` Linus Torvalds
@ 2026-03-02 18:55 ` David Laight
0 siblings, 0 replies; 14+ messages in thread
From: David Laight @ 2026-03-02 18:55 UTC (permalink / raw)
To: Linus Torvalds
Cc: Christophe Leroy (CS GROUP), Alexander Viro, Andre Almeida,
Andrew Cooper, Christian Borntraeger, Christian Brauner,
Christophe Leroy, Darren Hart, Davidlohr Bueso, Heiko Carstens,
Jan Kara, Julia Lawall, linux-arm-kernel, linux-fsdevel,
linuxppc-dev, linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
On Mon, 2 Mar 2026 09:26:31 -0800
Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Mon, 2 Mar 2026 at 06:59, Christophe Leroy (CS GROUP)
> <chleroy@kernel.org> wrote:
> >
> > Can we get this fix merged in 7.0-rc3 so that we can start building 7.1
> > on top of it ?
>
> Applied this first patch. I'm not so convinced about the others in the
> series, although people can always try to argue for them..
Patches 2 and 3 seemed a reasonable idea to me.
Removes a lot of code that is only there to make the whole thing work.
The 'with' is a bit of a take on Pascal - but without the 'making the
code completely unreadable' side effect.
I don't do WARN=1 builds, never mind WARN=2 :-)
Although -Wshadow can find real bugs - so I would turn it on and
suffer the annoyances.
Patch 5 was just what I was experimenting with.
Doing the equivalent change to the non-compat version (IIRC it
uses the (likely) much slower copy_to/from_user() because the
structures match) might even be more sensible.
David
>
> Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] uaccess: Disable -Wshadow in __scoped_user_access()
2026-03-02 15:00 ` Christophe Leroy (CS GROUP)
@ 2026-03-03 9:12 ` David Laight
0 siblings, 0 replies; 14+ messages in thread
From: David Laight @ 2026-03-03 9:12 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Darren Hart,
Davidlohr Bueso, Heiko Carstens, Jan Kara, Julia Lawall,
Linus Torvalds, linux-arm-kernel, linux-fsdevel, linuxppc-dev,
linux-riscv, linux-s390, LKML, Madhavan Srinivasan,
Mathieu Desnoyers, Michael Ellerman, Nicholas Piggin,
Nicolas Palix, Palmer Dabbelt, Paul Walmsley, Peter Zijlstra,
Russell King, Sven Schnelle, Thomas Gleixner, x86, Kees Cook,
akpm
On Mon, 2 Mar 2026 16:00:26 +0100
"Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
> Le 02/03/2026 à 14:27, david.laight.linux@gmail.com a écrit :
> > From: David Laight <david.laight.linux@gmail.com>
> >
> > -Wshadow is enabled by W=2 builds and __scoped_user_access() quite
> > deliberately creates a 'const' shadow of the 'user' address that
> > references a 'guard page' when the application passes a kernel pointer.
> >
> > Signed-off-by: David Laight <david.laight.linux@gmail.com>
>
> There is a problem with this patch:
(badly line-wrapped errors deleted)
It seems to need gcc 12.
(So Linus is in luck.)
Prior to gcc 12 the #pragma generated by _Pragma() act as the
controlled statement of the for () loop.
Trying to put the _Pragma() inside the for statement doesn't work at all.
David
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/5] uaccess: Disable -Wshadow in __scoped_user_access()
2026-03-02 13:27 ` [PATCH v2 4/5] uaccess: Disable -Wshadow " david.laight.linux
2026-03-02 15:00 ` Christophe Leroy (CS GROUP)
2026-03-02 17:17 ` Linus Torvalds
@ 2026-03-05 8:10 ` kernel test robot
2 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2026-03-05 8:10 UTC (permalink / raw)
To: david.laight.linux, Alexander Viro, Andre Almeida, Andrew Cooper,
Christian Borntraeger, Christian Brauner, Christophe Leroy,
Christophe Leroy (CS GROUP), Darren Hart, Davidlohr Bueso,
Heiko Carstens, Jan Kara, Julia Lawall, Linus Torvalds,
linux-arm-kernel, linux-fsdevel, linuxppc-dev, linux-riscv,
linux-s390, Madhavan Srinivasan, Mathieu Desnoyers,
Michael Ellerman, Nicholas Piggin, Nicolas Palix, Palmer Dabbelt,
Paul Walmsley, Peter Zijlstra, Russell King, Sven Schnelle
Cc: oe-kbuild-all, LKML
Hi,
kernel test robot noticed the following build errors:
[auto build test ERROR on brauner-vfs/vfs.all]
[also build test ERROR on v7.0-rc2]
[cannot apply to linus/master next-20260303]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/david-laight-linux-gmail-com/uaccess-Fix-scoped_user_read_access-for-pointer-to-const/20260302-213317
base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link: https://lore.kernel.org/r/20260302132755.1475451-5-david.laight.linux%40gmail.com
patch subject: [PATCH v2 4/5] uaccess: Disable -Wshadow in __scoped_user_access()
config: nios2-allnoconfig (https://download.01.org/0day-ci/archive/20260305/202603051642.i46zzlJ8-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260305/202603051642.i46zzlJ8-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603051642.i46zzlJ8-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
In file included from include/asm-generic/div64.h:27,
from ./arch/nios2/include/generated/asm/div64.h:1,
from include/linux/math.h:6,
from include/linux/math64.h:6,
from include/linux/time.h:6,
from include/linux/compat.h:10,
from kernel/futex/core.c:34:
kernel/futex/futex.h: In function 'futex_get_value_locked':
>> include/linux/uaccess.h:740:20: warning: unused variable '_tmpptr' [-Wunused-variable]
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~~~~
include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
>> include/linux/compiler.h:396:9: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
396 | for (declaration; !_with_done; _with_done = true)
| ^~~
include/linux/compiler.h:394:17: note: in expansion of macro 'and_with'
394 | and_with (declaration)
| ^~~~~~~~
include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
In file included from include/linux/compiler_types.h:173,
from <command-line>:
include/linux/compiler-gcc.h:118:33: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
118 | #define __diag(s) _Pragma(__diag_str(GCC diagnostic s))
| ^~~~~~~
include/linux/compiler-gcc.h:129:9: note: in expansion of macro '__diag'
129 | __diag(__diag_GCC_ignore option)
| ^~~~~~
include/linux/uaccess.h:742:31: note: in expansion of macro '__diag_ignore_all'
742 | __diag_push() __diag_ignore_all("-Wshadow", "uptr is readonly copy") \
| ^~~~~~~~~~~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
In file included from include/asm-generic/div64.h:27,
from ./arch/nios2/include/generated/asm/div64.h:1,
from include/linux/math.h:6,
from include/linux/math64.h:6,
from include/linux/time.h:6,
from include/linux/compat.h:10,
from kernel/futex/core.c:34:
>> include/linux/uaccess.h:743:90: error: '_tmpptr' undeclared (first use in this function)
743 | and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~
include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
include/linux/uaccess.h:743:90: note: each undeclared identifier is reported only once for each function it appears in
743 | and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~
include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
>> include/linux/compiler.h:396:28: error: '_with_done' undeclared (first use in this function)
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~
include/linux/uaccess.h:743:17: note: in expansion of macro 'and_with'
743 | and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/futex.h:288:16: note: in expansion of macro 'get_user_inline'
288 | return get_user_inline(*dest, from);
| ^~~~~~~~~~~~~~~
kernel/futex/core.c: In function 'get_futex_key':
>> include/linux/uaccess.h:740:20: warning: unused variable '_tmpptr' [-Wunused-variable]
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~~~~
include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
>> include/linux/compiler.h:396:9: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
396 | for (declaration; !_with_done; _with_done = true)
| ^~~
include/linux/compiler.h:394:17: note: in expansion of macro 'and_with'
394 | and_with (declaration)
| ^~~~~~~~
include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
In file included from include/linux/compiler_types.h:173,
from <command-line>:
include/linux/compiler-gcc.h:118:33: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
118 | #define __diag(s) _Pragma(__diag_str(GCC diagnostic s))
| ^~~~~~~
include/linux/compiler-gcc.h:129:9: note: in expansion of macro '__diag'
129 | __diag(__diag_GCC_ignore option)
| ^~~~~~
include/linux/uaccess.h:742:31: note: in expansion of macro '__diag_ignore_all'
742 | __diag_push() __diag_ignore_all("-Wshadow", "uptr is readonly copy") \
| ^~~~~~~~~~~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
In file included from include/asm-generic/div64.h:27,
from ./arch/nios2/include/generated/asm/div64.h:1,
from include/linux/math.h:6,
from include/linux/math64.h:6,
from include/linux/time.h:6,
from include/linux/compat.h:10,
from kernel/futex/core.c:34:
>> include/linux/uaccess.h:743:90: error: '_tmpptr' undeclared (first use in this function)
743 | and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~
include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
>> include/linux/compiler.h:396:28: error: '_with_done' undeclared (first use in this function)
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~
include/linux/uaccess.h:743:17: note: in expansion of macro 'and_with'
743 | and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
| ^~~~~~~~
include/linux/uaccess.h:755:9: note: in expansion of macro '__scoped_user_access'
755 | __scoped_user_access(read, usrc, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:767:9: note: in expansion of macro 'scoped_user_read_access_size'
767 | scoped_user_read_access_size(usrc, sizeof(*(usrc)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:831:9: note: in expansion of macro 'scoped_user_read_access'
831 | scoped_user_read_access(_tmpsrc, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:584:21: note: in expansion of macro 'get_user_inline'
584 | if (get_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
>> include/linux/uaccess.h:740:20: warning: unused variable '_tmpptr' [-Wunused-variable]
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~~~~
include/linux/compiler.h:396:14: note: in definition of macro 'and_with'
396 | for (declaration; !_with_done; _with_done = true)
| ^~~~~~~~~~~
include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~
include/linux/uaccess.h:778:9: note: in expansion of macro '__scoped_user_access'
778 | __scoped_user_access(write, udst, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:790:9: note: in expansion of macro 'scoped_user_write_access_size'
790 | scoped_user_write_access_size(udst, sizeof(*(udst)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:856:9: note: in expansion of macro 'scoped_user_write_access'
856 | scoped_user_write_access(_tmpdst, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:604:37: note: in expansion of macro 'put_user_inline'
604 | if (node_updated && put_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
>> include/linux/compiler.h:396:9: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
396 | for (declaration; !_with_done; _with_done = true)
| ^~~
include/linux/compiler.h:394:17: note: in expansion of macro 'and_with'
394 | and_with (declaration)
| ^~~~~~~~
include/linux/uaccess.h:740:9: note: in expansion of macro 'with'
740 | with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
| ^~~~
include/linux/uaccess.h:778:9: note: in expansion of macro '__scoped_user_access'
778 | __scoped_user_access(write, udst, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:790:9: note: in expansion of macro 'scoped_user_write_access_size'
790 | scoped_user_write_access_size(udst, sizeof(*(udst)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:856:9: note: in expansion of macro 'scoped_user_write_access'
856 | scoped_user_write_access(_tmpdst, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:604:37: note: in expansion of macro 'put_user_inline'
604 | if (node_updated && put_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
In file included from include/linux/compiler_types.h:173,
from <command-line>:
include/linux/compiler-gcc.h:118:33: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
118 | #define __diag(s) _Pragma(__diag_str(GCC diagnostic s))
| ^~~~~~~
include/linux/compiler-gcc.h:129:9: note: in expansion of macro '__diag'
129 | __diag(__diag_GCC_ignore option)
| ^~~~~~
include/linux/uaccess.h:742:31: note: in expansion of macro '__diag_ignore_all'
742 | __diag_push() __diag_ignore_all("-Wshadow", "uptr is readonly copy") \
| ^~~~~~~~~~~~~~~~~
include/linux/uaccess.h:778:9: note: in expansion of macro '__scoped_user_access'
778 | __scoped_user_access(write, udst, size, elbl)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:790:9: note: in expansion of macro 'scoped_user_write_access_size'
790 | scoped_user_write_access_size(udst, sizeof(*(udst)), elbl)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/uaccess.h:856:9: note: in expansion of macro 'scoped_user_write_access'
856 | scoped_user_write_access(_tmpdst, efault) \
| ^~~~~~~~~~~~~~~~~~~~~~~~
kernel/futex/core.c:604:37: note: in expansion of macro 'put_user_inline'
604 | if (node_updated && put_user_inline(node, naddr))
| ^~~~~~~~~~~~~~~
..
vim +/_tmpptr +743 include/linux/uaccess.h
689
690 /**
691 * __scoped_user_access - Open a scope for user access
692 * @mode: The mode of the access class (read, write, rw)
693 * @uptr: The pointer to access user space memory
694 * @size: Size of the access
695 * @elbl: Error label to goto when the access region is rejected. It
696 * must be placed outside the scope
697 *
698 * If the user access function inside the scope requires a fault label, it
699 * can use @elbl or a different label outside the scope, which requires
700 * that user access which is implemented with ASM GOTO has been properly
701 * wrapped. See unsafe_get_user() for reference.
702 *
703 * scoped_user_rw_access(ptr, efault) {
704 * unsafe_get_user(rval, &ptr->rval, efault);
705 * unsafe_put_user(wval, &ptr->wval, efault);
706 * }
707 * return 0;
708 * efault:
709 * return -EFAULT;
710 *
711 * The scope is internally implemented as a autoterminating nested for()
712 * loop, which can be left with 'return', 'break' and 'goto' at any
713 * point.
714 *
715 * When the scope is left user_##@_mode##_access_end() is automatically
716 * invoked.
717 *
718 * When the architecture supports masked user access and the access region
719 * which is determined by @uptr and @size is not a valid user space
720 * address, i.e. < TASK_SIZE, the scope sets the pointer to a faulting user
721 * space address and does not terminate early. This optimizes for the good
722 * case and lets the performance uncritical bad case go through the fault.
723 *
724 * The eventual modification of the pointer is limited to the scope.
725 * Outside of the scope the original pointer value is unmodified, so that
726 * the original pointer value is available for diagnostic purposes in an
727 * out of scope fault path.
728 *
729 * Nesting scoped user access into a user access scope is invalid and fails
730 * the build. Nesting into other guards, e.g. pagefault is safe.
731 *
732 * The masked variant does not check the size of the access and relies on a
733 * mapping hole (e.g. guard page) to catch an out of range pointer, the
734 * first access to user memory inside the scope has to be within
735 * @uptr ... @uptr + PAGE_SIZE - 1
736 *
737 * Don't use directly. Use scoped_masked_user_$MODE_access() instead.
738 */
739 #define __scoped_user_access(mode, uptr, size, elbl) \
> 740 with (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)) \
741 /* Force modified pointer usage within the scope */ \
742 __diag_push() __diag_ignore_all("-Wshadow", "uptr is readonly copy") \
> 743 and_with (const auto uptr __cleanup(__scoped_user_##mode##_access_end) = _tmpptr) \
744 __diag_pop()
745
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-03-05 8:11 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-02 13:27 [PATCH v2 0/5] uaccess: Updates to scoped_user_access() david.laight.linux
2026-03-02 13:27 ` [PATCH v2 1/5] uaccess: Fix scoped_user_read_access() for 'pointer to const' david.laight.linux
2026-03-02 14:59 ` Christophe Leroy (CS GROUP)
2026-03-02 17:26 ` Linus Torvalds
2026-03-02 18:55 ` David Laight
2026-03-02 13:27 ` [PATCH v2 2/5] compiler.h: Add generic support for 'autoterminating nested for() loops' david.laight.linux
2026-03-02 13:27 ` [PATCH v2 3/5] uaccess.h: Use with() and and_with() in __scoped_user_access() david.laight.linux
2026-03-02 13:27 ` [PATCH v2 4/5] uaccess: Disable -Wshadow " david.laight.linux
2026-03-02 15:00 ` Christophe Leroy (CS GROUP)
2026-03-03 9:12 ` David Laight
2026-03-02 17:17 ` Linus Torvalds
2026-03-05 8:10 ` kernel test robot
2026-03-02 13:27 ` [PATCH v2 next 5/5] signal: Use scoped_user_access() instead of __put/get_user() david.laight.linux
2026-03-02 16:07 ` Christophe Leroy (CS GROUP)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox