Skip to content

Commit 5b24a7a

Browse files
committed
Add 'unsafe' user access functions for batched accesses
The naming is meant to discourage random use: the helper functions are not really any more "unsafe" than the traditional double-underscore functions (which need the address range checking), but they do need even more infrastructure around them, and should not be used willy-nilly. In addition to checking the access range, these user access functions require that you wrap the user access with a "user_acess_{begin,end}()" around it. That allows architectures that implement kernel user access control (x86: SMAP, arm64: PAN) to do the user access control in the wrapping user_access_begin/end part, and then batch up the actual user space accesses using the new interfaces. The main (and hopefully only) use for these are for core generic access helpers, initially just the generic user string functions (strnlen_user() and strncpy_from_user()). Signed-off-by: Linus Torvalds <[email protected]>
1 parent 11f1a4b commit 5b24a7a

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

arch/x86/include/asm/uaccess.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,5 +762,30 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
762762
#undef __copy_from_user_overflow
763763
#undef __copy_to_user_overflow
764764

765+
/*
766+
* The "unsafe" user accesses aren't really "unsafe", but the naming
767+
* is a big fat warning: you have to not only do the access_ok()
768+
* checking before using them, but you have to surround them with the
769+
* user_access_begin/end() pair.
770+
*/
771+
#define user_access_begin() __uaccess_begin()
772+
#define user_access_end() __uaccess_end()
773+
774+
#define unsafe_put_user(x, ptr) \
775+
({ \
776+
int __pu_err; \
777+
__put_user_size((x), (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \
778+
__builtin_expect(__pu_err, 0); \
779+
})
780+
781+
#define unsafe_get_user(x, ptr) \
782+
({ \
783+
int __gu_err; \
784+
unsigned long __gu_val; \
785+
__get_user_size(__gu_val, (ptr), sizeof(*(ptr)), __gu_err, -EFAULT); \
786+
(x) = (__force __typeof__(*(ptr)))__gu_val; \
787+
__builtin_expect(__gu_err, 0); \
788+
})
789+
765790
#endif /* _ASM_X86_UACCESS_H */
766791

include/linux/uaccess.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,11 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);
111111
#define probe_kernel_address(addr, retval) \
112112
probe_kernel_read(&retval, addr, sizeof(retval))
113113

114+
#ifndef user_access_begin
115+
#define user_access_begin() do { } while (0)
116+
#define user_access_end() do { } while (0)
117+
#define unsafe_get_user(x, ptr) __get_user(x, ptr)
118+
#define unsafe_put_user(x, ptr) __put_user(x, ptr)
119+
#endif
120+
114121
#endif /* __LINUX_UACCESS_H__ */

0 commit comments

Comments
 (0)