diff --git a/headers/private/kernel/util/iovec_support.h b/headers/private/kernel/util/iovec_support.h index 9482d10af5..bf8d668b9c 100644 --- a/headers/private/kernel/util/iovec_support.h +++ b/headers/private/kernel/util/iovec_support.h @@ -14,7 +14,7 @@ get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs, bool permitNull = false) { // prevent integer overflow - if (vecCount > IOV_MAX) + if (vecCount > IOV_MAX || vecCount == 0) return B_BAD_VALUE; if (!IS_USER_ADDRESS(userVecs)) @@ -24,14 +24,24 @@ get_iovecs_from_user(const iovec* userVecs, size_t vecCount, iovec*& vecs, if (vecs == NULL) return B_NO_MEMORY; - if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) + if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) != B_OK) { + free(vecs); 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)) + if (!is_user_address_range(vecs[i].iov_base, vecs[i].iov_len)) { + free(vecs); return B_BAD_ADDRESS; + } + if (vecs[i].iov_len > SSIZE_MAX || total > (SSIZE_MAX - vecs[i].iov_len)) { + free(vecs); + return B_BAD_VALUE; + } + total += vecs[i].iov_len; } return B_OK;