From 013719cfc63815693a376fd0ca202b94d06124bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 11 Aug 2022 19:03:21 +0200 Subject: [PATCH] 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 00f1e7c5e40b41f892625b720c6a032b20f0c405 Change-Id: Ibf74ae2035b7e9c7a3db3613f60e06672ded4db0 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5542 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- headers/private/kernel/util/iovec_support.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) 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;