kernel: get_iovecs_from_user(): checks total iovec length against SSIZE_MAX
* the return type for recvmsg(), sendmsg(), readv(), writev() is ssize_t.
* check required by POSIX.
* fix memory leaks on failure introduced in 00f1e7c5e4
Change-Id: Ibf74ae2035b7e9c7a3db3613f60e06672ded4db0
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5542
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
c6e6743261
commit
013719cfc6
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user