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 12*65cdc13eSAugustin Cavalier typedef struct generic_io_vec { 13*65cdc13eSAugustin Cavalier generic_addr_t base; 14*65cdc13eSAugustin Cavalier generic_size_t length; 15*65cdc13eSAugustin Cavalier } generic_io_vec; 16*65cdc13eSAugustin Cavalier 17*65cdc13eSAugustin Cavalier 18*65cdc13eSAugustin Cavalier #ifdef IS_USER_ADDRESS 1900f1e7c5SAugustin Cavalier static inline status_t 2000f1e7c5SAugustin Cavalier get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs, 2100f1e7c5SAugustin Cavalier bool permitNull = false) 2200f1e7c5SAugustin Cavalier { 2300f1e7c5SAugustin Cavalier // prevent integer overflow 24013719cfSJérôme Duval if (vecCount > IOV_MAX || vecCount == 0) 2500f1e7c5SAugustin Cavalier return B_BAD_VALUE; 2600f1e7c5SAugustin Cavalier 2700f1e7c5SAugustin Cavalier if (!IS_USER_ADDRESS(userVecs)) 2800f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 2900f1e7c5SAugustin Cavalier 3000f1e7c5SAugustin Cavalier vecs = (iovec*)malloc(sizeof(iovec) * vecCount); 3100f1e7c5SAugustin Cavalier if (vecs == NULL) 3200f1e7c5SAugustin Cavalier return B_NO_MEMORY; 3300f1e7c5SAugustin Cavalier 34013719cfSJérôme Duval if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) { 35013719cfSJérôme Duval free(vecs); 3600f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 37013719cfSJérôme Duval } 3800f1e7c5SAugustin Cavalier 39013719cfSJérôme Duval size_t total = 0; 4000f1e7c5SAugustin Cavalier for (size_t i = 0; i < vecCount; i++) { 4100f1e7c5SAugustin Cavalier if (permitNull && vecs[i].iov_base == NULL) 4200f1e7c5SAugustin Cavalier continue; 43013719cfSJérôme Duval if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) { 44013719cfSJérôme Duval free(vecs); 4500f1e7c5SAugustin Cavalier return B_BAD_ADDRESS; 4600f1e7c5SAugustin Cavalier } 47013719cfSJérôme Duval if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) { 48013719cfSJérôme Duval free(vecs); 49013719cfSJérôme Duval return B_BAD_VALUE; 50013719cfSJérôme Duval } 51013719cfSJérôme Duval total += vecs[i].iov_len; 52013719cfSJérôme Duval } 5300f1e7c5SAugustin Cavalier 5400f1e7c5SAugustin Cavalier return B_OK; 5500f1e7c5SAugustin Cavalier } 56*65cdc13eSAugustin Cavalier #endif 5700f1e7c5SAugustin Cavalier 5800f1e7c5SAugustin Cavalier 5900f1e7c5SAugustin Cavalier #endif // _UTIL_IOVEC_SUPPORT_H 60