162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __ASM_GENERIC_UACCESS_H 362306a36Sopenharmony_ci#define __ASM_GENERIC_UACCESS_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * User space memory access functions, these should work 762306a36Sopenharmony_ci * on any machine that has kernel and user data in the same 862306a36Sopenharmony_ci * address space, e.g. all NOMMU machines. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <linux/string.h> 1162306a36Sopenharmony_ci#include <asm-generic/access_ok.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#ifdef CONFIG_UACCESS_MEMCPY 1462306a36Sopenharmony_ci#include <asm/unaligned.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic __always_inline int 1762306a36Sopenharmony_ci__get_user_fn(size_t size, const void __user *from, void *to) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci BUILD_BUG_ON(!__builtin_constant_p(size)); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci switch (size) { 2262306a36Sopenharmony_ci case 1: 2362306a36Sopenharmony_ci *(u8 *)to = *((u8 __force *)from); 2462306a36Sopenharmony_ci return 0; 2562306a36Sopenharmony_ci case 2: 2662306a36Sopenharmony_ci *(u16 *)to = get_unaligned((u16 __force *)from); 2762306a36Sopenharmony_ci return 0; 2862306a36Sopenharmony_ci case 4: 2962306a36Sopenharmony_ci *(u32 *)to = get_unaligned((u32 __force *)from); 3062306a36Sopenharmony_ci return 0; 3162306a36Sopenharmony_ci case 8: 3262306a36Sopenharmony_ci *(u64 *)to = get_unaligned((u64 __force *)from); 3362306a36Sopenharmony_ci return 0; 3462306a36Sopenharmony_ci default: 3562306a36Sopenharmony_ci BUILD_BUG(); 3662306a36Sopenharmony_ci return 0; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic __always_inline int 4362306a36Sopenharmony_ci__put_user_fn(size_t size, void __user *to, void *from) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci BUILD_BUG_ON(!__builtin_constant_p(size)); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci switch (size) { 4862306a36Sopenharmony_ci case 1: 4962306a36Sopenharmony_ci *(u8 __force *)to = *(u8 *)from; 5062306a36Sopenharmony_ci return 0; 5162306a36Sopenharmony_ci case 2: 5262306a36Sopenharmony_ci put_unaligned(*(u16 *)from, (u16 __force *)to); 5362306a36Sopenharmony_ci return 0; 5462306a36Sopenharmony_ci case 4: 5562306a36Sopenharmony_ci put_unaligned(*(u32 *)from, (u32 __force *)to); 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci case 8: 5862306a36Sopenharmony_ci put_unaligned(*(u64 *)from, (u64 __force *)to); 5962306a36Sopenharmony_ci return 0; 6062306a36Sopenharmony_ci default: 6162306a36Sopenharmony_ci BUILD_BUG(); 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label) \ 6862306a36Sopenharmony_cido { \ 6962306a36Sopenharmony_ci *((type *)dst) = get_unaligned((type *)(src)); \ 7062306a36Sopenharmony_ci if (0) /* make sure the label looks used to the compiler */ \ 7162306a36Sopenharmony_ci goto err_label; \ 7262306a36Sopenharmony_ci} while (0) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label) \ 7562306a36Sopenharmony_cido { \ 7662306a36Sopenharmony_ci put_unaligned(*((type *)src), (type *)(dst)); \ 7762306a36Sopenharmony_ci if (0) /* make sure the label looks used to the compiler */ \ 7862306a36Sopenharmony_ci goto err_label; \ 7962306a36Sopenharmony_ci} while (0) 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic inline __must_check unsigned long 8262306a36Sopenharmony_ciraw_copy_from_user(void *to, const void __user * from, unsigned long n) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci memcpy(to, (const void __force *)from, n); 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic inline __must_check unsigned long 8962306a36Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci memcpy((void __force *)to, from, n); 9262306a36Sopenharmony_ci return 0; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci#define INLINE_COPY_FROM_USER 9562306a36Sopenharmony_ci#define INLINE_COPY_TO_USER 9662306a36Sopenharmony_ci#endif /* CONFIG_UACCESS_MEMCPY */ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* 9962306a36Sopenharmony_ci * These are the main single-value transfer routines. They automatically 10062306a36Sopenharmony_ci * use the right size if we just have the right pointer type. 10162306a36Sopenharmony_ci * This version just falls back to copy_{from,to}_user, which should 10262306a36Sopenharmony_ci * provide a fast-path for small values. 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ci#define __put_user(x, ptr) \ 10562306a36Sopenharmony_ci({ \ 10662306a36Sopenharmony_ci __typeof__(*(ptr)) __x = (x); \ 10762306a36Sopenharmony_ci int __pu_err = -EFAULT; \ 10862306a36Sopenharmony_ci __chk_user_ptr(ptr); \ 10962306a36Sopenharmony_ci switch (sizeof (*(ptr))) { \ 11062306a36Sopenharmony_ci case 1: \ 11162306a36Sopenharmony_ci case 2: \ 11262306a36Sopenharmony_ci case 4: \ 11362306a36Sopenharmony_ci case 8: \ 11462306a36Sopenharmony_ci __pu_err = __put_user_fn(sizeof (*(ptr)), \ 11562306a36Sopenharmony_ci ptr, &__x); \ 11662306a36Sopenharmony_ci break; \ 11762306a36Sopenharmony_ci default: \ 11862306a36Sopenharmony_ci __put_user_bad(); \ 11962306a36Sopenharmony_ci break; \ 12062306a36Sopenharmony_ci } \ 12162306a36Sopenharmony_ci __pu_err; \ 12262306a36Sopenharmony_ci}) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define put_user(x, ptr) \ 12562306a36Sopenharmony_ci({ \ 12662306a36Sopenharmony_ci void __user *__p = (ptr); \ 12762306a36Sopenharmony_ci might_fault(); \ 12862306a36Sopenharmony_ci access_ok(__p, sizeof(*ptr)) ? \ 12962306a36Sopenharmony_ci __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) : \ 13062306a36Sopenharmony_ci -EFAULT; \ 13162306a36Sopenharmony_ci}) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#ifndef __put_user_fn 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic inline int __put_user_fn(size_t size, void __user *ptr, void *x) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#endif 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciextern int __put_user_bad(void) __attribute__((noreturn)); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define __get_user(x, ptr) \ 14762306a36Sopenharmony_ci({ \ 14862306a36Sopenharmony_ci int __gu_err = -EFAULT; \ 14962306a36Sopenharmony_ci __chk_user_ptr(ptr); \ 15062306a36Sopenharmony_ci switch (sizeof(*(ptr))) { \ 15162306a36Sopenharmony_ci case 1: { \ 15262306a36Sopenharmony_ci unsigned char __x = 0; \ 15362306a36Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 15462306a36Sopenharmony_ci ptr, &__x); \ 15562306a36Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 15662306a36Sopenharmony_ci break; \ 15762306a36Sopenharmony_ci }; \ 15862306a36Sopenharmony_ci case 2: { \ 15962306a36Sopenharmony_ci unsigned short __x = 0; \ 16062306a36Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 16162306a36Sopenharmony_ci ptr, &__x); \ 16262306a36Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 16362306a36Sopenharmony_ci break; \ 16462306a36Sopenharmony_ci }; \ 16562306a36Sopenharmony_ci case 4: { \ 16662306a36Sopenharmony_ci unsigned int __x = 0; \ 16762306a36Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 16862306a36Sopenharmony_ci ptr, &__x); \ 16962306a36Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 17062306a36Sopenharmony_ci break; \ 17162306a36Sopenharmony_ci }; \ 17262306a36Sopenharmony_ci case 8: { \ 17362306a36Sopenharmony_ci unsigned long long __x = 0; \ 17462306a36Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 17562306a36Sopenharmony_ci ptr, &__x); \ 17662306a36Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 17762306a36Sopenharmony_ci break; \ 17862306a36Sopenharmony_ci }; \ 17962306a36Sopenharmony_ci default: \ 18062306a36Sopenharmony_ci __get_user_bad(); \ 18162306a36Sopenharmony_ci break; \ 18262306a36Sopenharmony_ci } \ 18362306a36Sopenharmony_ci __gu_err; \ 18462306a36Sopenharmony_ci}) 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#define get_user(x, ptr) \ 18762306a36Sopenharmony_ci({ \ 18862306a36Sopenharmony_ci const void __user *__p = (ptr); \ 18962306a36Sopenharmony_ci might_fault(); \ 19062306a36Sopenharmony_ci access_ok(__p, sizeof(*ptr)) ? \ 19162306a36Sopenharmony_ci __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\ 19262306a36Sopenharmony_ci ((x) = (__typeof__(*(ptr)))0,-EFAULT); \ 19362306a36Sopenharmony_ci}) 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#ifndef __get_user_fn 19662306a36Sopenharmony_cistatic inline int __get_user_fn(size_t size, const void __user *ptr, void *x) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci#endif 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciextern int __get_user_bad(void) __attribute__((noreturn)); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* 20862306a36Sopenharmony_ci * Zero Userspace 20962306a36Sopenharmony_ci */ 21062306a36Sopenharmony_ci#ifndef __clear_user 21162306a36Sopenharmony_cistatic inline __must_check unsigned long 21262306a36Sopenharmony_ci__clear_user(void __user *to, unsigned long n) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci memset((void __force *)to, 0, n); 21562306a36Sopenharmony_ci return 0; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci#endif 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic inline __must_check unsigned long 22062306a36Sopenharmony_ciclear_user(void __user *to, unsigned long n) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci might_fault(); 22362306a36Sopenharmony_ci if (!access_ok(to, n)) 22462306a36Sopenharmony_ci return n; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return __clear_user(to, n); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci#include <asm/extable.h> 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci__must_check long strncpy_from_user(char *dst, const char __user *src, 23262306a36Sopenharmony_ci long count); 23362306a36Sopenharmony_ci__must_check long strnlen_user(const char __user *src, long n); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci#endif /* __ASM_GENERIC_UACCESS_H */ 236