100f1e7c5SAugustin Cavalier /* 200f1e7c5SAugustin Cavalier * Copyright 2022, Haiku, Inc. All rights reserved. 300f1e7c5SAugustin Cavalier * Distributed under the terms of the MIT license. 400f1e7c5SAugustin Cavalier */ 500f1e7c5SAugustin Cavalier #ifndef _UTIL_IOVEC_SUPPORT_H 600f1e7c5SAugustin Cavalier #define _UTIL_IOVEC_SUPPORT_H 700f1e7c5SAugustin Cavalier 800f1e7c5SAugustin Cavalier 900f1e7c5SAugustin Cavalier #include <KernelExport.h> 1000f1e7c5SAugustin Cavalier 1100f1e7c5SAugustin Cavalier 1200f1e7c5SAugustin Cavalier static inline status_t 1300f1e7c5SAugustin Cavalier get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs, 1400f1e7c5SAugustin Cavalier bool permitNull = false) 1500f1e7c5SAugustin Cavalier { 1600f1e7c5SAugustin Cavalier // prevent integer overflow 17*013719cfSJérôme Duval if (vecCount > IOV_MAX || vecCount == 0) 1800f1e7c5SAugustin Cavalier return B_BAD_VALUE; 1900f1e7c5SAugustin Cavalier 2000f1e7c5SAugustin Cavalier if (!IS_USER_ADDRESS(userVecs)) 2100f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 2200f1e7c5SAugustin Cavalier 2300f1e7c5SAugustin Cavalier vecs = (iovec*)malloc(sizeof(iovec) * vecCount); 2400f1e7c5SAugustin Cavalier if (vecs == NULL) 2500f1e7c5SAugustin Cavalier return B_NO_MEMORY; 2600f1e7c5SAugustin Cavalier 27*013719cfSJérôme Duval if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) { 28*013719cfSJérôme Duval free(vecs); 2900f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 30*013719cfSJérôme Duval } 3100f1e7c5SAugustin Cavalier 32*013719cfSJérôme Duval size_t total = 0; 3300f1e7c5SAugustin Cavalier for (size_t i = 0; i < vecCount; i++) { 3400f1e7c5SAugustin Cavalier if (permitNull && vecs[i].iov_base == NULL) 3500f1e7c5SAugustin Cavalier continue; 36*013719cfSJérôme Duval if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) { 37*013719cfSJérôme Duval free(vecs); 3800f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 3900f1e7c5SAugustin Cavalier } 40*013719cfSJérôme Duval if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) { 41*013719cfSJérôme Duval free(vecs); 42*013719cfSJérôme Duval return B_BAD_VALUE; 43*013719cfSJérôme Duval } 44*013719cfSJérôme Duval total += vecs[i].iov_len; 45*013719cfSJérôme Duval } 4600f1e7c5SAugustin Cavalier 4700f1e7c5SAugustin Cavalier return B_OK; 4800f1e7c5SAugustin Cavalier } 4900f1e7c5SAugustin Cavalier 5000f1e7c5SAugustin Cavalier 5100f1e7c5SAugustin Cavalier #endif // _UTIL_IOVEC_SUPPORT_H 52