haiku/headers/private/kernel/util/iovec_support.h
Augustin Cavalier 8e56b86bdd kernel: Use BStackOrHeapArray in fd & port vector I/O syscalls.
The socket syscall needs to still use the heap. Also add a comment
around get_iovecs_from_user() indicating what callers must do.
2024-06-25 21:33:20 -04:00

81 lines
1.8 KiB
C

/*
* Copyright 2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*/
#ifndef _UTIL_IOVEC_SUPPORT_H
#define _UTIL_IOVEC_SUPPORT_H
#include <KernelExport.h>
typedef struct generic_io_vec {
generic_addr_t base;
generic_size_t length;
} generic_io_vec;
#ifdef _KERNEL_VM_VM_H
static inline status_t
generic_memcpy(generic_addr_t dest, bool destPhysical, generic_addr_t src, bool srcPhysical,
generic_size_t size, bool user = false)
{
if (!srcPhysical && !destPhysical) {
if (user)
return user_memcpy((void*)dest, (void*)src, size);
memcpy((void*)dest, (void*)src, size);
return B_OK;
} else if (destPhysical && !srcPhysical) {
return vm_memcpy_to_physical(dest, (const void*)src, size, user);
} else if (!destPhysical && srcPhysical) {
return vm_memcpy_from_physical((void*)dest, src, size, user);
}
panic("generic_memcpy: physical -> physical not supported!");
return B_NOT_SUPPORTED;
}
#endif
#ifdef IS_USER_ADDRESS
/*!
* Copies an array of `iovec`s from userland.
* Callers must verify vecCount <= IOV_MAX and supply their own vecs buffer.
*/
static inline status_t
get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec* vecs,
bool permitNull = false)
{
if (vecCount == 0)
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userVecs))
return B_BAD_ADDRESS;
if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK)
return B_BAD_ADDRESS;
size_t total = 0;
for (size_t i = 0; i < vecCount; i++) {
if (permitNull && vecs[i].iov_base == NULL)
continue;
if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) {
return B_BAD_ADDRESS;
}
if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) {
return B_BAD_VALUE;
}
total += vecs[i].iov_len;
}
return B_OK;
}
#endif
#endif // _UTIL_IOVEC_SUPPORT_H