xref: /openbmc/linux/include/asm-generic/uaccess.h (revision 8f762fe5)
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 
12 #ifdef CONFIG_UACCESS_MEMCPY
13 static inline __must_check unsigned long
14 raw_copy_from_user(void *to, const void __user * from, unsigned long n)
15 {
16 	if (__builtin_constant_p(n)) {
17 		switch(n) {
18 		case 1:
19 			*(u8 *)to = *(u8 __force *)from;
20 			return 0;
21 		case 2:
22 			*(u16 *)to = *(u16 __force *)from;
23 			return 0;
24 		case 4:
25 			*(u32 *)to = *(u32 __force *)from;
26 			return 0;
27 #ifdef CONFIG_64BIT
28 		case 8:
29 			*(u64 *)to = *(u64 __force *)from;
30 			return 0;
31 #endif
32 		}
33 	}
34 
35 	memcpy(to, (const void __force *)from, n);
36 	return 0;
37 }
38 
39 static inline __must_check unsigned long
40 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
41 {
42 	if (__builtin_constant_p(n)) {
43 		switch(n) {
44 		case 1:
45 			*(u8 __force *)to = *(u8 *)from;
46 			return 0;
47 		case 2:
48 			*(u16 __force *)to = *(u16 *)from;
49 			return 0;
50 		case 4:
51 			*(u32 __force *)to = *(u32 *)from;
52 			return 0;
53 #ifdef CONFIG_64BIT
54 		case 8:
55 			*(u64 __force *)to = *(u64 *)from;
56 			return 0;
57 #endif
58 		default:
59 			break;
60 		}
61 	}
62 
63 	memcpy((void __force *)to, from, n);
64 	return 0;
65 }
66 #define INLINE_COPY_FROM_USER
67 #define INLINE_COPY_TO_USER
68 #endif /* CONFIG_UACCESS_MEMCPY */
69 
70 #define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
71 
72 #ifndef KERNEL_DS
73 #define KERNEL_DS	MAKE_MM_SEG(~0UL)
74 #endif
75 
76 #ifndef USER_DS
77 #define USER_DS		MAKE_MM_SEG(TASK_SIZE - 1)
78 #endif
79 
80 #ifndef get_fs
81 #define get_fs()	(current_thread_info()->addr_limit)
82 
83 static inline void set_fs(mm_segment_t fs)
84 {
85 	current_thread_info()->addr_limit = fs;
86 }
87 #endif
88 
89 #ifndef segment_eq
90 #define segment_eq(a, b) ((a).seg == (b).seg)
91 #endif
92 
93 #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size))
94 
95 /*
96  * The architecture should really override this if possible, at least
97  * doing a check on the get_fs()
98  */
99 #ifndef __access_ok
100 static inline int __access_ok(unsigned long addr, unsigned long size)
101 {
102 	return 1;
103 }
104 #endif
105 
106 /*
107  * These are the main single-value transfer routines.  They automatically
108  * use the right size if we just have the right pointer type.
109  * This version just falls back to copy_{from,to}_user, which should
110  * provide a fast-path for small values.
111  */
112 #define __put_user(x, ptr) \
113 ({								\
114 	__typeof__(*(ptr)) __x = (x);				\
115 	int __pu_err = -EFAULT;					\
116         __chk_user_ptr(ptr);                                    \
117 	switch (sizeof (*(ptr))) {				\
118 	case 1:							\
119 	case 2:							\
120 	case 4:							\
121 	case 8:							\
122 		__pu_err = __put_user_fn(sizeof (*(ptr)),	\
123 					 ptr, &__x);		\
124 		break;						\
125 	default:						\
126 		__put_user_bad();				\
127 		break;						\
128 	 }							\
129 	__pu_err;						\
130 })
131 
132 #define put_user(x, ptr)					\
133 ({								\
134 	void __user *__p = (ptr);				\
135 	might_fault();						\
136 	access_ok(__p, sizeof(*ptr)) ?		\
137 		__put_user((x), ((__typeof__(*(ptr)) __user *)__p)) :	\
138 		-EFAULT;					\
139 })
140 
141 #ifndef __put_user_fn
142 
143 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
144 {
145 	return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
146 }
147 
148 #define __put_user_fn(sz, u, k)	__put_user_fn(sz, u, k)
149 
150 #endif
151 
152 extern int __put_user_bad(void) __attribute__((noreturn));
153 
154 #define __get_user(x, ptr)					\
155 ({								\
156 	int __gu_err = -EFAULT;					\
157 	__chk_user_ptr(ptr);					\
158 	switch (sizeof(*(ptr))) {				\
159 	case 1: {						\
160 		unsigned char __x = 0;				\
161 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
162 					 ptr, &__x);		\
163 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
164 		break;						\
165 	};							\
166 	case 2: {						\
167 		unsigned short __x = 0;				\
168 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
169 					 ptr, &__x);		\
170 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
171 		break;						\
172 	};							\
173 	case 4: {						\
174 		unsigned int __x = 0;				\
175 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
176 					 ptr, &__x);		\
177 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
178 		break;						\
179 	};							\
180 	case 8: {						\
181 		unsigned long long __x = 0;			\
182 		__gu_err = __get_user_fn(sizeof (*(ptr)),	\
183 					 ptr, &__x);		\
184 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
185 		break;						\
186 	};							\
187 	default:						\
188 		__get_user_bad();				\
189 		break;						\
190 	}							\
191 	__gu_err;						\
192 })
193 
194 #define get_user(x, ptr)					\
195 ({								\
196 	const void __user *__p = (ptr);				\
197 	might_fault();						\
198 	access_ok(__p, sizeof(*ptr)) ?		\
199 		__get_user((x), (__typeof__(*(ptr)) __user *)__p) :\
200 		((x) = (__typeof__(*(ptr)))0,-EFAULT);		\
201 })
202 
203 #ifndef __get_user_fn
204 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
205 {
206 	return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
207 }
208 
209 #define __get_user_fn(sz, u, k)	__get_user_fn(sz, u, k)
210 
211 #endif
212 
213 extern int __get_user_bad(void) __attribute__((noreturn));
214 
215 /*
216  * Copy a null terminated string from userspace.
217  */
218 #ifndef __strncpy_from_user
219 static inline long
220 __strncpy_from_user(char *dst, const char __user *src, long count)
221 {
222 	char *tmp;
223 	strncpy(dst, (const char __force *)src, count);
224 	for (tmp = dst; *tmp && count > 0; tmp++, count--)
225 		;
226 	return (tmp - dst);
227 }
228 #endif
229 
230 static inline long
231 strncpy_from_user(char *dst, const char __user *src, long count)
232 {
233 	if (!access_ok(src, 1))
234 		return -EFAULT;
235 	return __strncpy_from_user(dst, src, count);
236 }
237 
238 /*
239  * Return the size of a string (including the ending 0)
240  *
241  * Return 0 on exception, a value greater than N if too long
242  */
243 #ifndef __strnlen_user
244 #define __strnlen_user(s, n) (strnlen((s), (n)) + 1)
245 #endif
246 
247 /*
248  * Unlike strnlen, strnlen_user includes the nul terminator in
249  * its returned count. Callers should check for a returned value
250  * greater than N as an indication the string is too long.
251  */
252 static inline long strnlen_user(const char __user *src, long n)
253 {
254 	if (!access_ok(src, 1))
255 		return 0;
256 	return __strnlen_user(src, n);
257 }
258 
259 /*
260  * Zero Userspace
261  */
262 #ifndef __clear_user
263 static inline __must_check unsigned long
264 __clear_user(void __user *to, unsigned long n)
265 {
266 	memset((void __force *)to, 0, n);
267 	return 0;
268 }
269 #endif
270 
271 static inline __must_check unsigned long
272 clear_user(void __user *to, unsigned long n)
273 {
274 	might_fault();
275 	if (!access_ok(to, n))
276 		return n;
277 
278 	return __clear_user(to, n);
279 }
280 
281 #include <asm/extable.h>
282 
283 #endif /* __ASM_GENERIC_UACCESS_H */
284