xref: /optee_os/core/include/kernel/user_access.h (revision 107f49d1023538268eb2f27eca235c798ecadb93)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  * Copyright (c) 2020, Linaro Limited
5  */
6 #ifndef __KERNEL_USER_ACCESS_H
7 #define __KERNEL_USER_ACCESS_H
8 
9 #include <assert.h>
10 #include <kernel/user_access_arch.h>
11 #include <tee_api_types.h>
12 #include <types_ext.h>
13 
14 #ifdef CFG_WITH_USER_TA
15 TEE_Result check_user_access(uint32_t flags, const void *uaddr, size_t len);
16 TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len);
17 TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len);
18 TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len);
19 TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len);
20 #else
21 static inline TEE_Result check_user_access(uint32_t flags __unused,
22 					   const void *uaddr __unused,
23 					   size_t len __unused)
24 {
25 	return TEE_ERROR_NOT_SUPPORTED;
26 }
27 
28 static inline TEE_Result copy_from_user_private(void *kaddr __unused,
29 						const void *uaddr __unused,
30 						size_t len __unused)
31 {
32 	return TEE_ERROR_NOT_SUPPORTED;
33 }
34 
35 static inline TEE_Result copy_from_user(void *kaddr __unused,
36 					const void *uaddr __unused,
37 					size_t len __unused)
38 {
39 	return TEE_ERROR_NOT_SUPPORTED;
40 }
41 
42 static inline TEE_Result copy_to_user_private(void *uaddr __unused,
43 					      const void *kaddr __unused,
44 					      size_t len __unused)
45 {
46 	return TEE_ERROR_NOT_SUPPORTED;
47 }
48 
49 static inline TEE_Result copy_to_user(void *uaddr __unused,
50 				      const void *kaddr __unused,
51 				      size_t len __unused)
52 {
53 	return TEE_ERROR_NOT_SUPPORTED;
54 }
55 #endif
56 
57 /*
58  * bb_alloc() - Allocate a bounce buffer
59  * @len:	Length of bounce buffer
60  *
61  * The bounce buffer is allocated from a per user TA context region reserved
62  * for bounce buffers. Buffers are allocated in a stack like fashion so
63  * only the last buffer can be free. Buffers generally don't have to be
64  * freed, all bounce buffer allocations are reset on each syscall entry.
65  *
66  * Return NULL on failure or a valid pointer on success.
67  */
68 void *bb_alloc(size_t len);
69 
70 /*
71  * bb_free() - Free a bounce buffer
72  * @bb:		Buffer
73  * @len:	Length of buffer
74  *
75  * The bounce buffer is only freed if it is last on the stack of allocated
76  * bounce buffers. This function does normally not need to be called, see
77  * description of bb_alloc().
78  */
79 void bb_free(void *bb, size_t len);
80 
81 /*
82  * bb_reset() - Reset bounce buffer allocation
83  *
84  * Resets the bounce buffer allocatation state, old pointers allocated
85  * with bb_alloc() should not be used any longer.
86  */
87 void bb_reset(void);
88 
89 TEE_Result clear_user(void *uaddr, size_t n);
90 
91 size_t strnlen_user(const void *s, size_t n);
92 
93 #define __BB_MEMDUP(memdup_func, src, len, p) ({			\
94 	TEE_Result __res = TEE_SUCCESS;					\
95 	void *__p = NULL;						\
96 									\
97 	__res = memdup_func((src), (len), &__p);			\
98 	if (!__res)							\
99 		*(p) = __p;						\
100 	__res;								\
101 })
102 
103 /*
104  * bb_memdup_user() - Duplicate a user-space buffer into a bounce buffer
105  * @src:    Pointer to the user buffer to be duplicated.
106  * @len:    Length of the user buffer to be duplicated.
107  * @p:      Holds duplicated bounce buffer on success, or unchanged on failure.
108  *          Note that the returned buffer is allocated by bb_alloc() and
109  *          normally doesn't have to be freed.
110  * Return TEE_SUCCESS on success.
111  * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error.
112  */
113 TEE_Result bb_memdup_user(const void *src, size_t len, void **p);
114 #define BB_MEMDUP_USER(src, len, p) \
115 	__BB_MEMDUP(bb_memdup_user, (src), (len), (p))
116 
117 /*
118  * bb_memdup_user_private() - Duplicate a private user-space buffer
119  * @src:    Pointer to the user buffer to be duplicated. The buffer should
120  *          be private to current TA (i.e., !TEE_MEMORY_ACCESS_ANY_OWNER).
121  * @len:    Length of the user buffer to be duplicated.
122  * @p:      Holds duplicated kernel buffer on success, or unchanged on failure.
123  *          Note that the returned buffer is allocated by bb_alloc() and
124  *          normally doesn't have to be freed.
125  * Return TEE_SUCCESS on success.
126  * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error.
127  */
128 TEE_Result bb_memdup_user_private(const void *src, size_t len, void **p);
129 #define BB_MEMDUP_USER_PRIVATE(src, len, p) \
130 	__BB_MEMDUP(bb_memdup_user_private, (src), (len), (p))
131 
132 /*
133  * bb_strndup_user() - Duplicate a user-space string into a bounce buffer
134  * @src:    Pointer to the user string to be duplicated.
135  * @maxlen: Maximum length of the user string
136  * @dst:    Holds duplicated string on success, or unchanged on failure.
137  * @dstlen: Length of string, excluding the terminating zero, returned in
138  *          @dst.
139  *
140  * Note that the returned buffer is allocated by bb_alloc() and normally
141  * doesn't have to be freed. But if it is to be freed the supplied length
142  * to bb_free() should be dstlen + 1.
143  *
144  * Return TEE_SUCCESS on success.
145  * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error.
146  */
147 TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst,
148 			   size_t *dstlen);
149 
150 TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr);
151 
152 uint32_t kaddr_to_uref(void *kaddr);
153 vaddr_t uref_to_vaddr(uint32_t uref);
154 static inline void *uref_to_kaddr(uint32_t uref)
155 {
156 	return (void *)uref_to_vaddr(uref);
157 }
158 
159 #define GET_USER_SCALAR(_x, _p) ({					\
160 	TEE_Result __res = TEE_SUCCESS;					\
161 	typeof(_p) __p = (_p);						\
162 									\
163 	static_assert(sizeof(_x) == sizeof(*__p));			\
164 									\
165 	__res = copy_from_user(&(_x), (const void *)__p, sizeof(*__p));	\
166 	__res;								\
167 })
168 
169 #define PUT_USER_SCALAR(_x, _p) ({					\
170 	TEE_Result __res = TEE_SUCCESS;					\
171 	typeof(_p) __p = (_p);						\
172 									\
173 	static_assert(sizeof(_x) == sizeof(*__p));			\
174 									\
175 	__res = copy_to_user((void *)__p, &(_x), sizeof(*__p));		\
176 	__res;								\
177 })
178 
179 #endif /*__KERNEL_USER_ACCESS_H*/
180