xref: /linux/include/asm-generic/uaccess.h (revision c02be2ad2b88c67c5d7c06b6aa7083b5b40e1077)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_GENERIC_UACCESS_H
3 #define __ASM_GENERIC_UACCESS_H
4 
5 /*
6  * User space memory access functions, these should work
7  * on any machine that has kernel and user data in the same
8  * address space, e.g. all NOMMU machines.
9  */
10 #include <linux/string.h>
11 #include <asm-generic/access_ok.h>
12 
13 #ifdef CONFIG_UACCESS_MEMCPY
14 #include <linux/unaligned.h>
15 
16 static __always_inline int
17 __get_user_fn(size_t size, const void __user *from, void *to)
18 {
19 	BUILD_BUG_ON(!__builtin_constant_p(size));
20 
21 	switch (size) {
22 	case 1:
23 		*(u8 *)to = *((u8 __force *)from);
24 		return 0;
25 	case 2:
26 		*(u16 *)to = get_unaligned((u16 __force *)from);
27 		return 0;
28 	case 4:
29 		*(u32 *)to = get_unaligned((u32 __force *)from);
30 		return 0;
31 	case 8:
32 		*(u64 *)to = get_unaligned((u64 __force *)from);
33 		return 0;
34 	default:
35 		BUILD_BUG();
36 		return 0;
37 	}
38 
39 }
40 #define __get_user_fn(sz, u, k)	__get_user_fn(sz, u, k)
41 
42 static __always_inline int
43 __put_user_fn(size_t size, void __user *to, void *from)
44 {
45 	BUILD_BUG_ON(!__builtin_constant_p(size));
46 
47 	switch (size) {
48 	case 1:
49 		*(u8 __force *)to = *(u8 *)from;
50 		return 0;
51 	case 2:
52 		put_unaligned(*(u16 *)from, (u16 __force *)to);
53 		return 0;
54 	case 4:
55 		put_unaligned(*(u32 *)from, (u32 __force *)to);
56 		return 0;
57 	case 8:
58 		put_unaligned(*(u64 *)from, (u64 __force *)to);
59 		return 0;
60 	default:
61 		BUILD_BUG();
62 		return 0;
63 	}
64 }
65 #define __put_user_fn(sz, u, k)	__put_user_fn(sz, u, k)
66 
67 #define __get_kernel_nofault(dst, src, type, err_label)			\
68 do {									\
69 	*((type *)dst) = get_unaligned((type *)(src));			\
70 	if (0) /* make sure the label looks used to the compiler */	\
71 		goto err_label;						\
72 } while (0)
73 
74 #define __put_kernel_nofault(dst, src, type, err_label)			\
75 do {									\
76 	put_unaligned(*((type *)src), (type *)(dst));			\
77 	if (0) /* make sure the label looks used to the compiler */	\
78 		goto err_label;						\
79 } while (0)
80 
81 static inline __must_check unsigned long
82 raw_copy_from_user(void *to, const void __user * from, unsigned long n)
83 {
84 	memcpy(to, (const void __force *)from, n);
85 	return 0;
86 }
87 
88 static inline __must_check unsigned long
89 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
90 {
91 	memcpy((void __force *)to, from, n);
92 	return 0;
93 }
94 #define INLINE_COPY_USER
95 #endif /* CONFIG_UACCESS_MEMCPY */
96 
97 /*
98  * These are the main single-value transfer routines.  They automatically
99  * use the right size if we just have the right pointer type.
100  * This version just falls back to copy_{from,to}_user, which should
101  * provide a fast-path for small values.
102  */
103 #define __put_user(x, ptr) \
104 ({								\
105 	__typeof__(*(ptr)) __x = (x);				\
106 	int __pu_err = -EFAULT;					\
107         __chk_user_ptr(ptr);                                    \
108 	switch (sizeof (*(ptr))) {				\
109 	case 1:							\
110 	case 2:							\
111 	case 4:							\
112 	case 8:							\
113 		__pu_err = __put_user_fn(sizeof (*(ptr)),	\
114 					 ptr, &__x);		\
115 		break;						\
116 	default:						\
117 		__put_user_bad();				\
118 		break;						\
119 	 }							\
120 	__pu_err;						\
121 })
122 
123 #define put_user(x, ptr)					\
124 ({								\
125 	void __user *__p = (ptr);				\
126 	might_fault();						\
127 	access_ok(__p, sizeof(*ptr)) ?		\
128 		__put_user((x), ((__typeof__(*(ptr)) __user *)__p)) :	\
129 		-EFAULT;					\
130 })
131 
132 #ifndef __put_user_fn
133 
134 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
135 {
136 	return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
137 }
138 
139 #define __put_user_fn(sz, u, k)	__put_user_fn(sz, u, k)
140 
141 #endif
142 
143 extern int __put_user_bad(void) __attribute__((noreturn));
144 
145 #define __get_user(x, ptr)					\
146 ({								\
147 	int __gu_err = -EFAULT;					\
148 	__chk_user_ptr(ptr);					\
149 	switch (sizeof(*(ptr))) {				\
150 	case 1: {						\
151 		unsigned char __x = 0;				\
152 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
153 					 ptr, &__x);		\
154 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
155 		break;						\
156 	};							\
157 	case 2: {						\
158 		unsigned short __x = 0;				\
159 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
160 					 ptr, &__x);		\
161 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
162 		break;						\
163 	};							\
164 	case 4: {						\
165 		unsigned int __x = 0;				\
166 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
167 					 ptr, &__x);		\
168 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
169 		break;						\
170 	};							\
171 	case 8: {						\
172 		unsigned long long __x = 0;			\
173 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
174 					 ptr, &__x);		\
175 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
176 		break;						\
177 	};							\
178 	default:						\
179 		__get_user_bad();				\
180 		break;						\
181 	}							\
182 	__gu_err;						\
183 })
184 
185 #define get_user(x, ptr)					\
186 ({								\
187 	const void __user *__p = (ptr);				\
188 	might_fault();						\
189 	access_ok(__p, sizeof(*ptr)) ?		\
190 		__get_user((x), (__typeof__(*(ptr)) __user *)__p) :\
191 		((x) = (__typeof__(*(ptr)))0,-EFAULT);		\
192 })
193 
194 #ifndef __get_user_fn
195 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
196 {
197 	return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
198 }
199 
200 #define __get_user_fn(sz, u, k)	__get_user_fn(sz, u, k)
201 
202 #endif
203 
204 extern int __get_user_bad(void) __attribute__((noreturn));
205 
206 /*
207  * Zero Userspace
208  */
209 #ifndef __clear_user
210 static inline __must_check unsigned long
211 __clear_user(void __user *to, unsigned long n)
212 {
213 	memset((void __force *)to, 0, n);
214 	return 0;
215 }
216 #endif
217 
218 static inline __must_check unsigned long
219 clear_user(void __user *to, unsigned long n)
220 {
221 	might_fault();
222 	if (!access_ok(to, n))
223 		return n;
224 
225 	return __clear_user(to, n);
226 }
227 
228 #include <asm/extable.h>
229 
230 __must_check long strncpy_from_user(char *dst, const char __user *src,
231 				    long count);
232 __must_check long strnlen_user(const char __user *src, long n);
233 
234 #endif /* __ASM_GENERIC_UACCESS_H */
235