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