]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
uaccess: Fix scoped_user_read_access() for 'pointer to const'
authorDavid Laight <david.laight.linux@gmail.com>
Mon, 2 Mar 2026 13:27:51 +0000 (13:27 +0000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 2 Mar 2026 17:24:32 +0000 (09:24 -0800)
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-and-tested-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/uaccess.h

index 1f3804245c06679d4c124f350352d8dc37d56219..809e4f7dfdbd4d4426ef38457ae108f119cb1bee 100644 (file)
@@ -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