]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
uaccess: Provide put/get_user_inline()
authorThomas Gleixner <tglx@linutronix.de>
Mon, 27 Oct 2025 08:43:56 +0000 (09:43 +0100)
committerIngo Molnar <mingo@kernel.org>
Tue, 4 Nov 2025 07:28:15 +0000 (08:28 +0100)
Provide convenience wrappers around scoped user access similar to
put/get_user(), which reduce the usage sites to:

       if (!get_user_inline(val, ptr))
        return -EFAULT;

Should only be used if there is a demonstrable performance benefit.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Link: https://patch.msgid.link/20251027083745.609031602@linutronix.de
include/linux/uaccess.h

index 5f142c05b0dc877eb2ea2890c9cf8958d2976bd4..be395f5f7ee31108c654b25b02891383eae7011e 100644 (file)
@@ -825,6 +825,56 @@ for (bool done = false; !done; done = true)                                                \
 #define scoped_user_rw_access(uptr, elbl)                              \
        scoped_user_rw_access_size(uptr, sizeof(*(uptr)), elbl)
 
+/**
+ * get_user_inline - Read user data inlined
+ * @val:       The variable to store the value read from user memory
+ * @usrc:      Pointer to the user space memory to read from
+ *
+ * Return: 0 if successful, -EFAULT when faulted
+ *
+ * Inlined variant of get_user(). Only use when there is a demonstrable
+ * performance reason.
+ */
+#define get_user_inline(val, usrc)                             \
+({                                                             \
+       __label__ efault;                                       \
+       typeof(usrc) _tmpsrc = usrc;                            \
+       int _ret = 0;                                           \
+                                                               \
+       scoped_user_read_access(_tmpsrc, efault)                \
+               unsafe_get_user(val, _tmpsrc, efault);          \
+       if (0) {                                                \
+       efault:                                                 \
+               _ret = -EFAULT;                                 \
+       }                                                       \
+       _ret;                                                   \
+})
+
+/**
+ * put_user_inline - Write to user memory inlined
+ * @val:       The value to write
+ * @udst:      Pointer to the user space memory to write to
+ *
+ * Return: 0 if successful, -EFAULT when faulted
+ *
+ * Inlined variant of put_user(). Only use when there is a demonstrable
+ * performance reason.
+ */
+#define put_user_inline(val, udst)                             \
+({                                                             \
+       __label__ efault;                                       \
+       typeof(udst) _tmpdst = udst;                            \
+       int _ret = 0;                                           \
+                                                               \
+       scoped_user_write_access(_tmpdst, efault)               \
+               unsafe_put_user(val, _tmpdst, efault);          \
+       if (0) {                                                \
+       efault:                                                 \
+               _ret = -EFAULT;                                 \
+       }                                                       \
+       _ret;                                                   \
+})
+
 #ifdef CONFIG_HARDENED_USERCOPY
 void __noreturn usercopy_abort(const char *name, const char *detail,
                               bool to_user, unsigned long offset,