xref: /haiku/headers/private/kernel/util/iovec_support.h (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
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 typedef struct generic_io_vec {
13 	generic_addr_t	base;
14 	generic_size_t	length;
15 } generic_io_vec;
16 
17 
18 #ifdef _KERNEL_VM_VM_H
19 
20 static inline status_t
21 generic_memcpy(generic_addr_t dest, bool destPhysical, generic_addr_t src, bool srcPhysical,
22 	generic_size_t size, bool user = false)
23 {
24 	if (!srcPhysical && !destPhysical) {
25 		if (user)
26 			return user_memcpy((void*)dest, (void*)src, size);
27 		memcpy((void*)dest, (void*)src, size);
28 		return B_OK;
29 	} else if (destPhysical && !srcPhysical) {
30 		return vm_memcpy_to_physical(dest, (const void*)src, size, user);
31 	} else if (!destPhysical && srcPhysical) {
32 		return vm_memcpy_from_physical((void*)dest, src, size, user);
33 	}
34 
35 	panic("generic_memcpy: physical -> physical not supported!");
36 	return B_NOT_SUPPORTED;
37 }
38 
39 #endif
40 
41 
42 #ifdef IS_USER_ADDRESS
43 
44 static inline status_t
45 get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs,
46 	bool permitNull = false)
47 {
48 	// prevent integer overflow
49 	if (vecCount > IOV_MAX || vecCount == 0)
50 		return B_BAD_VALUE;
51 
52 	if (!IS_USER_ADDRESS(userVecs))
53 		return B_BAD_ADDRESS;
54 
55 	vecs = (iovec*)malloc(sizeof(iovec) * vecCount);
56 	if (vecs == NULL)
57 		return B_NO_MEMORY;
58 
59 	if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) {
60 		free(vecs);
61 		return B_BAD_ADDRESS;
62 	}
63 
64 	size_t total = 0;
65 	for (size_t i = 0; i < vecCount; i++) {
66 		if (permitNull && vecs[i].iov_base == NULL)
67 			continue;
68 		if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) {
69 			free(vecs);
70 			return B_BAD_ADDRESS;
71 		}
72 		if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) {
73 			free(vecs);
74 			return B_BAD_VALUE;
75 		}
76 		total += vecs[i].iov_len;
77 	}
78 
79 	return B_OK;
80 }
81 
82 #endif
83 
84 
85 #endif	// _UTIL_IOVEC_SUPPORT_H
86