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
check_user_access(uint32_t flags __unused,const void * uaddr __unused,size_t len __unused)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
copy_from_user_private(void * kaddr __unused,const void * uaddr __unused,size_t len __unused)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
copy_from_user(void * kaddr __unused,const void * uaddr __unused,size_t len __unused)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
copy_to_user_private(void * uaddr __unused,const void * kaddr __unused,size_t len __unused)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
copy_to_user(void * uaddr __unused,const void * kaddr __unused,size_t len __unused)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_free_wipe() - Wipe and free a bounce buffer
83 * @bb: Buffer
84 * @len: Length of buffer
85 *
86 * The bounce buffer is always wiped if @bb is non-NULL, but only freed if
87 * it is last on the stack of allocated bounce buffers.
88 */
89 void bb_free_wipe(void *bb, size_t len);
90
91 /*
92 * bb_reset() - Reset bounce buffer allocation
93 *
94 * Resets the bounce buffer allocatation state, old pointers allocated
95 * with bb_alloc() should not be used any longer.
96 */
97 void bb_reset(void);
98
99 TEE_Result clear_user(void *uaddr, size_t n);
100
101 size_t strnlen_user(const void *s, size_t n);
102
103 #define __BB_MEMDUP(memdup_func, src, len, p) ({ \
104 TEE_Result __res = TEE_SUCCESS; \
105 void *__p = NULL; \
106 \
107 __res = memdup_func((src), (len), &__p); \
108 if (!__res) \
109 *(p) = __p; \
110 __res; \
111 })
112
113 /*
114 * bb_memdup_user() - Duplicate a user-space buffer into a bounce buffer
115 * @src: Pointer to the user buffer to be duplicated.
116 * @len: Length of the user buffer to be duplicated.
117 * @p: Holds duplicated bounce buffer on success, or unchanged on failure.
118 * Note that the returned buffer is allocated by bb_alloc() and
119 * normally doesn't have to be freed.
120 * Return TEE_SUCCESS on success.
121 * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error.
122 */
123 TEE_Result bb_memdup_user(const void *src, size_t len, void **p);
124 #define BB_MEMDUP_USER(src, len, p) \
125 __BB_MEMDUP(bb_memdup_user, (src), (len), (p))
126
127 /*
128 * bb_memdup_user_private() - Duplicate a private user-space buffer
129 * @src: Pointer to the user buffer to be duplicated. The buffer should
130 * be private to current TA (i.e., !TEE_MEMORY_ACCESS_ANY_OWNER).
131 * @len: Length of the user buffer to be duplicated.
132 * @p: Holds duplicated kernel buffer on success, or unchanged on failure.
133 * Note that the returned buffer is allocated by bb_alloc() and
134 * normally doesn't have to be freed.
135 * Return TEE_SUCCESS on success.
136 * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error.
137 */
138 TEE_Result bb_memdup_user_private(const void *src, size_t len, void **p);
139 #define BB_MEMDUP_USER_PRIVATE(src, len, p) \
140 __BB_MEMDUP(bb_memdup_user_private, (src), (len), (p))
141
142 /*
143 * bb_strndup_user() - Duplicate a user-space string into a bounce buffer
144 * @src: Pointer to the user string to be duplicated.
145 * @maxlen: Maximum length of the user string
146 * @dst: Holds duplicated string on success, or unchanged on failure.
147 * @dstlen: Length of string, excluding the terminating zero, returned in
148 * @dst.
149 *
150 * Note that the returned buffer is allocated by bb_alloc() and normally
151 * doesn't have to be freed. But if it is to be freed the supplied length
152 * to bb_free() should be dstlen + 1.
153 *
154 * Return TEE_SUCCESS on success.
155 * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error.
156 */
157 TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst,
158 size_t *dstlen);
159
160 TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr);
161
162 uint32_t kaddr_to_uref(void *kaddr);
163 vaddr_t uref_to_vaddr(uint32_t uref);
uref_to_kaddr(uint32_t uref)164 static inline void *uref_to_kaddr(uint32_t uref)
165 {
166 return (void *)uref_to_vaddr(uref);
167 }
168
169 #define GET_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_from_user(&(_x), (const void *)__p, sizeof(*__p)); \
176 __res; \
177 })
178
179 #define PUT_USER_SCALAR(_x, _p) ({ \
180 TEE_Result __res = TEE_SUCCESS; \
181 typeof(_p) __p = (_p); \
182 \
183 static_assert(sizeof(_x) == sizeof(*__p)); \
184 \
185 __res = copy_to_user((void *)__p, &(_x), sizeof(*__p)); \
186 __res; \
187 })
188
189 #endif /*__KERNEL_USER_ACCESS_H*/
190