1 /* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #ifndef _SYSCALL_PUB_H 32 #define _SYSCALL_PUB_H 33 34 #include <stdlib.h> 35 #include "los_memory.h" 36 #include "los_vm_lock.h" 37 #include "los_vm_map.h" 38 #include "user_copy.h" 39 #include "fs/fs.h" 40 #include "fcntl.h" 41 #include "los_strncpy_from_user.h" 42 43 extern int CheckRegion(const LosVmSpace *space, VADDR_T ptr, size_t len); 44 extern void *DupUserMem(const void *ptr, size_t len, int needCopy); 45 extern int GetFullpath(int fd, const char *path, char **fullpath); 46 extern int UserPathCopy(const char *userPath, char **pathBuf); 47 48 #define CHECK_ASPACE(ptr, len, ...) \ 49 do { \ 50 if (ptr != NULL && len != 0) { \ 51 if (!LOS_IsUserAddressRange((VADDR_T)(UINTPTR)ptr, len)) { \ 52 set_errno(EFAULT); \ 53 __VA_ARGS__; \ 54 return -get_errno(); \ 55 } \ 56 LosVmSpace *__aspace = OsCurrProcessGet()->vmSpace; \ 57 (VOID)LOS_MuxAcquire(&__aspace->regionMux); \ 58 if (CheckRegion(__aspace, (VADDR_T)(UINTPTR)ptr, len) == -1) { \ 59 (VOID)LOS_MuxRelease(&__aspace->regionMux); \ 60 set_errno(EFAULT); \ 61 __VA_ARGS__; \ 62 return -get_errno(); \ 63 } \ 64 (VOID)LOS_MuxRelease(&__aspace->regionMux); \ 65 } \ 66 } while (0) 67 68 #define LEN(ptr) ((ptr) ? *(ptr) : 0) 69 70 #define DUP_FROM_USER_(ptr, size, copy, ...) \ 71 __typeof(ptr) ptr##bak = ptr; \ 72 if (ptr != NULL && (size) != 0) { \ 73 ptr = DupUserMem(ptr, size, copy); \ 74 if (ptr == NULL) { \ 75 ptr = ptr##bak; \ 76 __VA_ARGS__; \ 77 return -get_errno(); \ 78 } \ 79 } 80 81 /* 82 DUP_FROM_USER(ptr, size, ...) can not deal with "char *"; 83 Please deal with the "char *" by function:UserPathCopy. 84 */ 85 #define DUP_FROM_USER(ptr, size, ...) \ 86 DUP_FROM_USER_(ptr, size, 1, ##__VA_ARGS__) 87 88 #define DUP_FROM_USER_NOCOPY(ptr, size, ...) \ 89 DUP_FROM_USER_(ptr, size, 0, ##__VA_ARGS__) 90 91 #define DUP_TO_USER(ptr, size, ...) \ 92 do { \ 93 if (ptr != NULL && (size) != 0) { \ 94 if (LOS_ArchCopyToUser(ptr##bak, ptr, size) != 0) { \ 95 set_errno(EFAULT); \ 96 __VA_ARGS__; \ 97 return -get_errno(); \ 98 } \ 99 } \ 100 } while (0) 101 102 #define FREE_DUP(ptr) \ 103 do { \ 104 if (ptr != ptr##bak) { \ 105 LOS_MemFree(OS_SYS_MEM_ADDR, (void*)ptr); \ 106 ptr = ptr##bak; \ 107 } \ 108 } while (0) 109 110 #define CPY_FROM_USER(ptr) \ 111 __typeof(*ptr) ptr##cpy = {0}, *ptr##bak = ptr; \ 112 if (ptr != NULL) { \ 113 if (LOS_ArchCopyFromUser((void*)&ptr##cpy, ptr##bak, sizeof(*ptr##bak)) != 0) { \ 114 set_errno(EFAULT); \ 115 return -get_errno(); \ 116 } \ 117 ptr = &ptr##cpy; \ 118 } 119 120 #define CPY_TO_USER(ptr, ...) \ 121 if (ptr != NULL) { \ 122 if (LOS_ArchCopyToUser(ptr##bak, ptr, sizeof(*ptr)) != 0) { \ 123 set_errno(EFAULT); \ 124 __VA_ARGS__; \ 125 return -get_errno(); \ 126 } \ 127 } 128 129 /** Macros for sendmsg and recvmsg */ 130 131 #define CONST_CAST(ptr) ((__typeof(ptr##_NONCONST))ptr) 132 133 #define CHECK_FIELD_ASPACE(ptr, field, len) \ 134 do { \ 135 if (ptr != NULL) { \ 136 CHECK_ASPACE(ptr->field, len); \ 137 } \ 138 } while (0) 139 140 #define CHECK_ARRAY_FIELD_ASPACE(ptr, arr, arrlen, field, len, ...) \ 141 do { \ 142 if (ptr != NULL && ptr->arr != NULL) { \ 143 for (size_t i = 0; i < arrlen; i++) { \ 144 CHECK_ASPACE(ptr->arr[i].field, ptr->arr[i].len, ##__VA_ARGS__); \ 145 } \ 146 } \ 147 } while (0) 148 149 #define DUP_FIELD_FROM_USER_(ptr, field, size, copy, ...) \ 150 do { \ 151 if (ptr != NULL && ptr->field != NULL && (size) != 0) { \ 152 CONST_CAST(ptr)->field = DupUserMem(ptr->field, size, copy); \ 153 if (ptr->field == NULL) { \ 154 __VA_ARGS__; \ 155 return -get_errno(); \ 156 } \ 157 } \ 158 } while (0) 159 160 #define DUP_FIELD_FROM_USER(ptr, field, size, ...) \ 161 DUP_FIELD_FROM_USER_(ptr, field, size, 1, ##__VA_ARGS__) 162 163 #define DUP_FIELD_FROM_USER_NOCOPY(ptr, field, size, ...) \ 164 DUP_FIELD_FROM_USER_(ptr, field, size, 0, ##__VA_ARGS__) 165 166 /* backup the arr to ptr##arr */ 167 #define DUP_ARRAY_FIELD_FROM_USER_(ext, ptr, arr, arrlen, field, len, ...) \ 168 __typeof(*ptr##_NONCONST) ptr##arr##cpy = ptr##cpybak, ptr##arr##cpybak = ptr##cpybak; \ 169 __typeof(ptr##_NONCONST) ptr##arr = ptr ? &ptr##arr##cpy : NULL, ptr##arr##_NONCONST = NULL; \ 170 DUP_FIELD_FROM_USER(ptr##arr, arr, arrlen * sizeof(ptr->arr[0]), ##__VA_ARGS__); \ 171 if (ptr != NULL && ptr->arr != NULL) { \ 172 size_t i = 0; \ 173 for (; i < arrlen; i++) { \ 174 DUP_FIELD_FROM_USER##ext(ptr, arr[i].field, ptr->arr[i].len, break); \ 175 } \ 176 if (i != arrlen) { \ 177 FREE_DUP_ARRAY_FIELD(ptr, arr, i, field); \ 178 __VA_ARGS__; \ 179 return -get_errno(); \ 180 } \ 181 } 182 183 #define DUP_ARRAY_FIELD_FROM_USER(ptr, arr, arrlen, field, len, ...) \ 184 DUP_ARRAY_FIELD_FROM_USER_(, ptr, arr, arrlen, field, len, ##__VA_ARGS__) 185 186 #define DUP_ARRAY_FIELD_FROM_USER_NOCOPY(ptr, arr, arrlen, field, len, ...) \ 187 DUP_ARRAY_FIELD_FROM_USER_(_NOCOPY, ptr, arr, arrlen, field, len, ##__VA_ARGS__) 188 189 #define FREE_DUP_FIELD(ptr, field) \ 190 do { \ 191 if (ptr != NULL && ptr->field != ptr##cpybak.field) { \ 192 LOS_MemFree(OS_SYS_MEM_ADDR, (void*)ptr->field); \ 193 CONST_CAST(ptr)->field = ptr##cpybak.field; \ 194 } \ 195 } while (0) 196 197 /* use and free the backuped arr in ptr##arr */ 198 #define FREE_DUP_ARRAY_FIELD(ptr, arr, arrlen, field) \ 199 if (ptr != NULL && ptr->arr != NULL && arrlen != 0) { \ 200 __typeof(ptr##cpybak.arr) tmp = ptr##cpybak.arr; \ 201 ptr##cpybak.arr = ptr##arr->arr; \ 202 for (size_t j = 0; j < arrlen; j++) { \ 203 FREE_DUP_FIELD(ptr, arr[j].field); \ 204 } \ 205 ptr##cpybak.arr = tmp; \ 206 } \ 207 FREE_DUP_FIELD(ptr##arr, arr); 208 209 #define CPY_FROM_CONST_USER(NonConstType, ptr) \ 210 CPY_FROM_USER(ptr); \ 211 NonConstType *ptr##_NONCONST = NULL, ptr##cpybak = ptr##cpy; \ 212 (void)ptr##bak; 213 214 #define CPY_FROM_NONCONST_USER(ptr) \ 215 CPY_FROM_USER(ptr); \ 216 __typeof(*ptr) *ptr##_NONCONST = NULL, ptr##cpybak = ptr##cpy; 217 218 #define DUP_FIELD_TO_USER(ptr, field, size, ...) \ 219 do { \ 220 if (ptr != NULL && ptr->field != NULL && (size) != 0) { \ 221 if (LOS_ArchCopyToUser(ptr##cpybak.field, ptr->field, size) != 0 || \ 222 LOS_ArchCopyToUser(&ptr##bak->field, &ptr##cpybak.field, sizeof(__typeof(ptr##cpybak.field))) != 0) { \ 223 set_errno(EFAULT); \ 224 __VA_ARGS__; \ 225 return -get_errno(); \ 226 } \ 227 } \ 228 } while (0) 229 230 /* use the backuped arr from ptr##arr */ 231 #define DUP_ARRAY_FIELD_TO_USER(ptr, arr, arrlen, field, len, ...) \ 232 if (ptr != NULL && ptr->arr != NULL) { \ 233 __typeof(ptr##cpybak.arr) tmp = ptr##cpybak.arr; \ 234 __typeof(ptr##bak) tmp2 = ptr##bak; \ 235 ptr##cpybak.arr = ptr##arr->arr; \ 236 ptr##arr->arr = tmp; \ 237 ptr##bak = ptr##arr; \ 238 for (size_t i = 0; i < arrlen; i++) { \ 239 DUP_FIELD_TO_USER(ptr, arr[i].field, ptr->arr[i].len, ##__VA_ARGS__); \ 240 } \ 241 ptr##bak = tmp2; \ 242 ptr##arr->arr = ptr##cpybak.arr; \ 243 ptr##cpybak.arr = tmp; \ 244 } 245 246 #define PointerFree(ptr) \ 247 do { \ 248 if (ptr != NULL) { \ 249 LOS_MemFree(OS_SYS_MEM_ADDR, (void*)ptr); \ 250 } \ 251 } while (0) 252 #endif 253