5b24a7a2aa
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 <torvalds@linux-foundation.org>
121 lines
3.5 KiB
C
121 lines
3.5 KiB
C
#ifndef __LINUX_UACCESS_H__
|
|
#define __LINUX_UACCESS_H__
|
|
|
|
#include <linux/sched.h>
|
|
#include <asm/uaccess.h>
|
|
|
|
static __always_inline void pagefault_disabled_inc(void)
|
|
{
|
|
current->pagefault_disabled++;
|
|
}
|
|
|
|
static __always_inline void pagefault_disabled_dec(void)
|
|
{
|
|
current->pagefault_disabled--;
|
|
WARN_ON(current->pagefault_disabled < 0);
|
|
}
|
|
|
|
/*
|
|
* These routines enable/disable the pagefault handler. If disabled, it will
|
|
* not take any locks and go straight to the fixup table.
|
|
*
|
|
* User access methods will not sleep when called from a pagefault_disabled()
|
|
* environment.
|
|
*/
|
|
static inline void pagefault_disable(void)
|
|
{
|
|
pagefault_disabled_inc();
|
|
/*
|
|
* make sure to have issued the store before a pagefault
|
|
* can hit.
|
|
*/
|
|
barrier();
|
|
}
|
|
|
|
static inline void pagefault_enable(void)
|
|
{
|
|
/*
|
|
* make sure to issue those last loads/stores before enabling
|
|
* the pagefault handler again.
|
|
*/
|
|
barrier();
|
|
pagefault_disabled_dec();
|
|
}
|
|
|
|
/*
|
|
* Is the pagefault handler disabled? If so, user access methods will not sleep.
|
|
*/
|
|
#define pagefault_disabled() (current->pagefault_disabled != 0)
|
|
|
|
/*
|
|
* The pagefault handler is in general disabled by pagefault_disable() or
|
|
* when in irq context (via in_atomic()).
|
|
*
|
|
* This function should only be used by the fault handlers. Other users should
|
|
* stick to pagefault_disabled().
|
|
* Please NEVER use preempt_disable() to disable the fault handler. With
|
|
* !CONFIG_PREEMPT_COUNT, this is like a NOP. So the handler won't be disabled.
|
|
* in_atomic() will report different values based on !CONFIG_PREEMPT_COUNT.
|
|
*/
|
|
#define faulthandler_disabled() (pagefault_disabled() || in_atomic())
|
|
|
|
#ifndef ARCH_HAS_NOCACHE_UACCESS
|
|
|
|
static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
|
|
const void __user *from, unsigned long n)
|
|
{
|
|
return __copy_from_user_inatomic(to, from, n);
|
|
}
|
|
|
|
static inline unsigned long __copy_from_user_nocache(void *to,
|
|
const void __user *from, unsigned long n)
|
|
{
|
|
return __copy_from_user(to, from, n);
|
|
}
|
|
|
|
#endif /* ARCH_HAS_NOCACHE_UACCESS */
|
|
|
|
/*
|
|
* probe_kernel_read(): safely attempt to read from a location
|
|
* @dst: pointer to the buffer that shall take the data
|
|
* @src: address to read from
|
|
* @size: size of the data chunk
|
|
*
|
|
* Safely read from address @src to the buffer at @dst. If a kernel fault
|
|
* happens, handle that and return -EFAULT.
|
|
*/
|
|
extern long probe_kernel_read(void *dst, const void *src, size_t size);
|
|
extern long __probe_kernel_read(void *dst, const void *src, size_t size);
|
|
|
|
/*
|
|
* probe_kernel_write(): safely attempt to write to a location
|
|
* @dst: address to write to
|
|
* @src: pointer to the data that shall be written
|
|
* @size: size of the data chunk
|
|
*
|
|
* Safely write to address @dst from the buffer at @src. If a kernel fault
|
|
* happens, handle that and return -EFAULT.
|
|
*/
|
|
extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
|
|
extern long notrace __probe_kernel_write(void *dst, const void *src, size_t size);
|
|
|
|
extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);
|
|
|
|
/**
|
|
* probe_kernel_address(): safely attempt to read from a location
|
|
* @addr: address to read from
|
|
* @retval: read into this variable
|
|
*
|
|
* Returns 0 on success, or -EFAULT.
|
|
*/
|
|
#define probe_kernel_address(addr, retval) \
|
|
probe_kernel_read(&retval, addr, sizeof(retval))
|
|
|
|
#ifndef user_access_begin
|
|
#define user_access_begin() do { } while (0)
|
|
#define user_access_end() do { } while (0)
|
|
#define unsafe_get_user(x, ptr) __get_user(x, ptr)
|
|
#define unsafe_put_user(x, ptr) __put_user(x, ptr)
|
|
#endif
|
|
|
|
#endif /* __LINUX_UACCESS_H__ */
|