18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __ASM_GENERIC_UACCESS_H 38c2ecf20Sopenharmony_ci#define __ASM_GENERIC_UACCESS_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * User space memory access functions, these should work 78c2ecf20Sopenharmony_ci * on any machine that has kernel and user data in the same 88c2ecf20Sopenharmony_ci * address space, e.g. all NOMMU machines. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <linux/string.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifdef CONFIG_UACCESS_MEMCPY 138c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic __always_inline int 168c2ecf20Sopenharmony_ci__get_user_fn(size_t size, const void __user *from, void *to) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci BUILD_BUG_ON(!__builtin_constant_p(size)); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci switch (size) { 218c2ecf20Sopenharmony_ci case 1: 228c2ecf20Sopenharmony_ci *(u8 *)to = get_unaligned((u8 __force *)from); 238c2ecf20Sopenharmony_ci return 0; 248c2ecf20Sopenharmony_ci case 2: 258c2ecf20Sopenharmony_ci *(u16 *)to = get_unaligned((u16 __force *)from); 268c2ecf20Sopenharmony_ci return 0; 278c2ecf20Sopenharmony_ci case 4: 288c2ecf20Sopenharmony_ci *(u32 *)to = get_unaligned((u32 __force *)from); 298c2ecf20Sopenharmony_ci return 0; 308c2ecf20Sopenharmony_ci case 8: 318c2ecf20Sopenharmony_ci *(u64 *)to = get_unaligned((u64 __force *)from); 328c2ecf20Sopenharmony_ci return 0; 338c2ecf20Sopenharmony_ci default: 348c2ecf20Sopenharmony_ci BUILD_BUG(); 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic __always_inline int 428c2ecf20Sopenharmony_ci__put_user_fn(size_t size, void __user *to, void *from) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci BUILD_BUG_ON(!__builtin_constant_p(size)); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci switch (size) { 478c2ecf20Sopenharmony_ci case 1: 488c2ecf20Sopenharmony_ci put_unaligned(*(u8 *)from, (u8 __force *)to); 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci case 2: 518c2ecf20Sopenharmony_ci put_unaligned(*(u16 *)from, (u16 __force *)to); 528c2ecf20Sopenharmony_ci return 0; 538c2ecf20Sopenharmony_ci case 4: 548c2ecf20Sopenharmony_ci put_unaligned(*(u32 *)from, (u32 __force *)to); 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci case 8: 578c2ecf20Sopenharmony_ci put_unaligned(*(u64 *)from, (u64 __force *)to); 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci default: 608c2ecf20Sopenharmony_ci BUILD_BUG(); 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label) \ 678c2ecf20Sopenharmony_cido { \ 688c2ecf20Sopenharmony_ci *((type *)dst) = get_unaligned((type *)(src)); \ 698c2ecf20Sopenharmony_ci if (0) /* make sure the label looks used to the compiler */ \ 708c2ecf20Sopenharmony_ci goto err_label; \ 718c2ecf20Sopenharmony_ci} while (0) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label) \ 748c2ecf20Sopenharmony_cido { \ 758c2ecf20Sopenharmony_ci put_unaligned(*((type *)src), (type *)(dst)); \ 768c2ecf20Sopenharmony_ci if (0) /* make sure the label looks used to the compiler */ \ 778c2ecf20Sopenharmony_ci goto err_label; \ 788c2ecf20Sopenharmony_ci} while (0) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define HAVE_GET_KERNEL_NOFAULT 1 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic inline __must_check unsigned long 838c2ecf20Sopenharmony_ciraw_copy_from_user(void *to, const void __user * from, unsigned long n) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci memcpy(to, (const void __force *)from, n); 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic inline __must_check unsigned long 908c2ecf20Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci memcpy((void __force *)to, from, n); 938c2ecf20Sopenharmony_ci return 0; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci#define INLINE_COPY_FROM_USER 968c2ecf20Sopenharmony_ci#define INLINE_COPY_TO_USER 978c2ecf20Sopenharmony_ci#endif /* CONFIG_UACCESS_MEMCPY */ 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#ifdef CONFIG_SET_FS 1008c2ecf20Sopenharmony_ci#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci#ifndef KERNEL_DS 1038c2ecf20Sopenharmony_ci#define KERNEL_DS MAKE_MM_SEG(~0UL) 1048c2ecf20Sopenharmony_ci#endif 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#ifndef USER_DS 1078c2ecf20Sopenharmony_ci#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) 1088c2ecf20Sopenharmony_ci#endif 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#ifndef get_fs 1118c2ecf20Sopenharmony_ci#define get_fs() (current_thread_info()->addr_limit) 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic inline void set_fs(mm_segment_t fs) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci current_thread_info()->addr_limit = fs; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci#endif 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#ifndef uaccess_kernel 1208c2ecf20Sopenharmony_ci#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 1218c2ecf20Sopenharmony_ci#endif 1228c2ecf20Sopenharmony_ci#endif /* CONFIG_SET_FS */ 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci#define access_ok(addr, size) __access_ok((unsigned long)(addr),(size)) 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/* 1278c2ecf20Sopenharmony_ci * The architecture should really override this if possible, at least 1288c2ecf20Sopenharmony_ci * doing a check on the get_fs() 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_ci#ifndef __access_ok 1318c2ecf20Sopenharmony_cistatic inline int __access_ok(unsigned long addr, unsigned long size) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci return 1; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci#endif 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* 1388c2ecf20Sopenharmony_ci * These are the main single-value transfer routines. They automatically 1398c2ecf20Sopenharmony_ci * use the right size if we just have the right pointer type. 1408c2ecf20Sopenharmony_ci * This version just falls back to copy_{from,to}_user, which should 1418c2ecf20Sopenharmony_ci * provide a fast-path for small values. 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_ci#define __put_user(x, ptr) \ 1448c2ecf20Sopenharmony_ci({ \ 1458c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __x = (x); \ 1468c2ecf20Sopenharmony_ci int __pu_err = -EFAULT; \ 1478c2ecf20Sopenharmony_ci __chk_user_ptr(ptr); \ 1488c2ecf20Sopenharmony_ci switch (sizeof (*(ptr))) { \ 1498c2ecf20Sopenharmony_ci case 1: \ 1508c2ecf20Sopenharmony_ci case 2: \ 1518c2ecf20Sopenharmony_ci case 4: \ 1528c2ecf20Sopenharmony_ci case 8: \ 1538c2ecf20Sopenharmony_ci __pu_err = __put_user_fn(sizeof (*(ptr)), \ 1548c2ecf20Sopenharmony_ci ptr, &__x); \ 1558c2ecf20Sopenharmony_ci break; \ 1568c2ecf20Sopenharmony_ci default: \ 1578c2ecf20Sopenharmony_ci __put_user_bad(); \ 1588c2ecf20Sopenharmony_ci break; \ 1598c2ecf20Sopenharmony_ci } \ 1608c2ecf20Sopenharmony_ci __pu_err; \ 1618c2ecf20Sopenharmony_ci}) 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#define put_user(x, ptr) \ 1648c2ecf20Sopenharmony_ci({ \ 1658c2ecf20Sopenharmony_ci void __user *__p = (ptr); \ 1668c2ecf20Sopenharmony_ci might_fault(); \ 1678c2ecf20Sopenharmony_ci access_ok(__p, sizeof(*ptr)) ? \ 1688c2ecf20Sopenharmony_ci __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) : \ 1698c2ecf20Sopenharmony_ci -EFAULT; \ 1708c2ecf20Sopenharmony_ci}) 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#ifndef __put_user_fn 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic inline int __put_user_fn(size_t size, void __user *ptr, void *x) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci#endif 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciextern int __put_user_bad(void) __attribute__((noreturn)); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci#define __get_user(x, ptr) \ 1868c2ecf20Sopenharmony_ci({ \ 1878c2ecf20Sopenharmony_ci int __gu_err = -EFAULT; \ 1888c2ecf20Sopenharmony_ci __chk_user_ptr(ptr); \ 1898c2ecf20Sopenharmony_ci switch (sizeof(*(ptr))) { \ 1908c2ecf20Sopenharmony_ci case 1: { \ 1918c2ecf20Sopenharmony_ci unsigned char __x = 0; \ 1928c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 1938c2ecf20Sopenharmony_ci ptr, &__x); \ 1948c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 1958c2ecf20Sopenharmony_ci break; \ 1968c2ecf20Sopenharmony_ci }; \ 1978c2ecf20Sopenharmony_ci case 2: { \ 1988c2ecf20Sopenharmony_ci unsigned short __x = 0; \ 1998c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 2008c2ecf20Sopenharmony_ci ptr, &__x); \ 2018c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2028c2ecf20Sopenharmony_ci break; \ 2038c2ecf20Sopenharmony_ci }; \ 2048c2ecf20Sopenharmony_ci case 4: { \ 2058c2ecf20Sopenharmony_ci unsigned int __x = 0; \ 2068c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 2078c2ecf20Sopenharmony_ci ptr, &__x); \ 2088c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2098c2ecf20Sopenharmony_ci break; \ 2108c2ecf20Sopenharmony_ci }; \ 2118c2ecf20Sopenharmony_ci case 8: { \ 2128c2ecf20Sopenharmony_ci unsigned long long __x = 0; \ 2138c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(sizeof (*(ptr)), \ 2148c2ecf20Sopenharmony_ci ptr, &__x); \ 2158c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2168c2ecf20Sopenharmony_ci break; \ 2178c2ecf20Sopenharmony_ci }; \ 2188c2ecf20Sopenharmony_ci default: \ 2198c2ecf20Sopenharmony_ci __get_user_bad(); \ 2208c2ecf20Sopenharmony_ci break; \ 2218c2ecf20Sopenharmony_ci } \ 2228c2ecf20Sopenharmony_ci __gu_err; \ 2238c2ecf20Sopenharmony_ci}) 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci#define get_user(x, ptr) \ 2268c2ecf20Sopenharmony_ci({ \ 2278c2ecf20Sopenharmony_ci const void __user *__p = (ptr); \ 2288c2ecf20Sopenharmony_ci might_fault(); \ 2298c2ecf20Sopenharmony_ci access_ok(__p, sizeof(*ptr)) ? \ 2308c2ecf20Sopenharmony_ci __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\ 2318c2ecf20Sopenharmony_ci ((x) = (__typeof__(*(ptr)))0,-EFAULT); \ 2328c2ecf20Sopenharmony_ci}) 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci#ifndef __get_user_fn 2358c2ecf20Sopenharmony_cistatic inline int __get_user_fn(size_t size, const void __user *ptr, void *x) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci#endif 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ciextern int __get_user_bad(void) __attribute__((noreturn)); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/* 2478c2ecf20Sopenharmony_ci * Copy a null terminated string from userspace. 2488c2ecf20Sopenharmony_ci */ 2498c2ecf20Sopenharmony_ci#ifndef __strncpy_from_user 2508c2ecf20Sopenharmony_cistatic inline long 2518c2ecf20Sopenharmony_ci__strncpy_from_user(char *dst, const char __user *src, long count) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci char *tmp; 2548c2ecf20Sopenharmony_ci strncpy(dst, (const char __force *)src, count); 2558c2ecf20Sopenharmony_ci for (tmp = dst; *tmp && count > 0; tmp++, count--) 2568c2ecf20Sopenharmony_ci ; 2578c2ecf20Sopenharmony_ci return (tmp - dst); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci#endif 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic inline long 2628c2ecf20Sopenharmony_cistrncpy_from_user(char *dst, const char __user *src, long count) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci if (!access_ok(src, 1)) 2658c2ecf20Sopenharmony_ci return -EFAULT; 2668c2ecf20Sopenharmony_ci return __strncpy_from_user(dst, src, count); 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/* 2708c2ecf20Sopenharmony_ci * Return the size of a string (including the ending 0) 2718c2ecf20Sopenharmony_ci * 2728c2ecf20Sopenharmony_ci * Return 0 on exception, a value greater than N if too long 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_ci#ifndef __strnlen_user 2758c2ecf20Sopenharmony_ci#define __strnlen_user(s, n) (strnlen((s), (n)) + 1) 2768c2ecf20Sopenharmony_ci#endif 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci/* 2798c2ecf20Sopenharmony_ci * Unlike strnlen, strnlen_user includes the nul terminator in 2808c2ecf20Sopenharmony_ci * its returned count. Callers should check for a returned value 2818c2ecf20Sopenharmony_ci * greater than N as an indication the string is too long. 2828c2ecf20Sopenharmony_ci */ 2838c2ecf20Sopenharmony_cistatic inline long strnlen_user(const char __user *src, long n) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci if (!access_ok(src, 1)) 2868c2ecf20Sopenharmony_ci return 0; 2878c2ecf20Sopenharmony_ci return __strnlen_user(src, n); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * Zero Userspace 2928c2ecf20Sopenharmony_ci */ 2938c2ecf20Sopenharmony_ci#ifndef __clear_user 2948c2ecf20Sopenharmony_cistatic inline __must_check unsigned long 2958c2ecf20Sopenharmony_ci__clear_user(void __user *to, unsigned long n) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci memset((void __force *)to, 0, n); 2988c2ecf20Sopenharmony_ci return 0; 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci#endif 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic inline __must_check unsigned long 3038c2ecf20Sopenharmony_ciclear_user(void __user *to, unsigned long n) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci might_fault(); 3068c2ecf20Sopenharmony_ci if (!access_ok(to, n)) 3078c2ecf20Sopenharmony_ci return n; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return __clear_user(to, n); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci#include <asm/extable.h> 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci#endif /* __ASM_GENERIC_UACCESS_H */ 315