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