This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 2777d0d058a net/socket: validate msg_iovlen against IOV_MAX and
non-zero in sendmsg/recvmsg
2777d0d058a is described below
commit 2777d0d058a78a78ac0a1392612f8a651b97e818
Author: Swatantra Yadav <[email protected]>
AuthorDate: Sat Nov 7 14:14:10 2026 +0530
net/socket: validate msg_iovlen against IOV_MAX and non-zero in
sendmsg/recvmsg
POSIX IEEE Std 1003.1 explicitly specifies for both sendmsg() and recvmsg():
"[EMSGSIZE] The msg_iovlen member of the msghdr structure is less than
or equal to 0 or is greater than {IOV_MAX}."
Neither psock_sendmsg() nor psock_recvmsg() validated msg->msg_iovlen.
Passing msg_iovlen = 0 or msg_iovlen > IOV_MAX caused:
1. In psock_recvmsg(), dereferencing msg->msg_iov->iov_base on an empty
iovec array, or returning -EINVAL instead of the mandated -EMSGSIZE.
2. In net/usrsock (usrsock_sendmsg.c), allocating an unbounded variable-
length array on the kernel stack (struct iovec bufs[2 +
msg->msg_iovlen]),
leading to kernel stack overflow when msg_iovlen is large.
3. In net/local (local_sendmsg.c) and net/rpmsg (rpmsg_sockif.c),
executing zero-length loops, sending empty preambles, or unhandled
states.
4. Requiring individual lower-level drivers (inet, can, local_recvmsg) to
redundantly duplicate ad-hoc checks for msg->msg_iovlen == 0.
This patch adds upfront validation of msg->msg_iovlen against 0 and
IOV_MAX in psock_sendmsg() and psock_recvmsg(), returning -EMSGSIZE on
violation, while also ensuring psock is verified before dereferencing
psock->s_type.
Assisted-by: Google Gemini:gemini-3.8-flash
Signed-off-by: Swatantra Yadav <[email protected]>
---
net/socket/recvmsg.c | 25 +++++++++++++++++++------
net/socket/sendmsg.c | 23 ++++++++++++++++++-----
2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/net/socket/recvmsg.c b/net/socket/recvmsg.c
index 9543c6b6f6e..318b63c34a1 100644
--- a/net/socket/recvmsg.c
+++ b/net/socket/recvmsg.c
@@ -28,6 +28,7 @@
#include <assert.h>
#include <errno.h>
+#include <limits.h>
#include <nuttx/cancelpt.h>
#include <nuttx/fs/fs.h>
@@ -76,23 +77,35 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct
msghdr *msg,
FAR void *msg_control;
int ret;
+ /* Verify that the sockfd corresponds to valid, allocated socket */
+
+ if (psock == NULL || psock->s_conn == NULL)
+ {
+ return -EBADF;
+ }
+
/* Verify that non-NULL pointers were passed */
- if (msg == NULL || msg->msg_iov == NULL || msg->msg_iov->iov_base == NULL)
+ if (msg == NULL)
{
return -EINVAL;
}
- if (msg->msg_name != NULL && msg->msg_namelen <= 0)
+ /* POSIX: fail with EMSGSIZE if msg_iovlen <= 0 or > IOV_MAX */
+
+ if (msg->msg_iovlen == 0 || msg->msg_iovlen > IOV_MAX)
{
- return -EINVAL;
+ return -EMSGSIZE;
}
- /* Verify that the sockfd corresponds to valid, allocated socket */
+ if (msg->msg_iov == NULL || msg->msg_iov->iov_base == NULL)
+ {
+ return -EINVAL;
+ }
- if (psock == NULL || psock->s_conn == NULL)
+ if (msg->msg_name != NULL && msg->msg_namelen <= 0)
{
- return -EBADF;
+ return -EINVAL;
}
/* Let logic specific to this address family handle the recvmsg()
diff --git a/net/socket/sendmsg.c b/net/socket/sendmsg.c
index 7ead5ca11b5..36aab568d67 100644
--- a/net/socket/sendmsg.c
+++ b/net/socket/sendmsg.c
@@ -29,6 +29,7 @@
#include <sys/socket.h>
#include <assert.h>
#include <errno.h>
+#include <limits.h>
#include <signal.h>
#include <nuttx/cancelpt.h>
@@ -76,19 +77,31 @@
ssize_t psock_sendmsg(FAR struct socket *psock, FAR const struct msghdr *msg,
int flags)
{
+ /* Verify that the sockfd corresponds to valid, allocated socket */
+
+ if (psock == NULL || psock->s_conn == NULL)
+ {
+ return -EBADF;
+ }
+
/* Verify that non-NULL pointers were passed */
- if (msg == NULL || msg->msg_iov == NULL ||
- (psock->s_type != SOCK_DGRAM && msg->msg_iov->iov_base == NULL))
+ if (msg == NULL)
{
return -EINVAL;
}
- /* Verify that the sockfd corresponds to valid, allocated socket */
+ /* POSIX: fail with EMSGSIZE if msg_iovlen <= 0 or > IOV_MAX */
- if (psock == NULL || psock->s_conn == NULL)
+ if (msg->msg_iovlen == 0 || msg->msg_iovlen > IOV_MAX)
{
- return -EBADF;
+ return -EMSGSIZE;
+ }
+
+ if (msg->msg_iov == NULL ||
+ (psock->s_type != SOCK_DGRAM && msg->msg_iov->iov_base == NULL))
+ {
+ return -EINVAL;
}
/* Let logic specific to this address family handle the sendmsg()