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
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
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
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
© 2016 - 2026 Red Hat, Inc.