xref: /haiku/headers/private/kernel/util/iovec_support.h (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2022, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT license.
4  */
5 #ifndef _UTIL_IOVEC_SUPPORT_H
6 #define _UTIL_IOVEC_SUPPORT_H
7 
8 
9 #include <KernelExport.h>
10 
11 
12 static inline status_t
13 get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs,
14 	bool permitNull = false)
15 {
16 	// prevent integer overflow
17 	if (vecCount > IOV_MAX || vecCount == 0)
18 		return B_BAD_VALUE;
19 
20 	if (!IS_USER_ADDRESS(userVecs))
21 		return B_BAD_ADDRESS;
22 
23 	vecs = (iovec*)malloc(sizeof(iovec) * vecCount);
24 	if (vecs == NULL)
25 		return B_NO_MEMORY;
26 
27 	if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) {
28 		free(vecs);
29 		return B_BAD_ADDRESS;
30 	}
31 
32 	size_t total = 0;
33 	for (size_t i = 0; i < vecCount; i++) {
34 		if (permitNull && vecs[i].iov_base == NULL)
35 			continue;
36 		if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) {
37 			free(vecs);
38 			return B_BAD_ADDRESS;
39 		}
40 		if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) {
41 			free(vecs);
42 			return B_BAD_VALUE;
43 		}
44 		total += vecs[i].iov_len;
45 	}
46 
47 	return B_OK;
48 }
49 
50 
51 #endif	// _UTIL_IOVEC_SUPPORT_H
52