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_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); 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