This is an automated email from the ASF dual-hosted git repository.
michallenc 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 b6c4e4636c5 net/rpmsg: fix integer overflow in sendmsg and datagram
truncation
b6c4e4636c5 is described below
commit b6c4e4636c5a0176bcae3a504cbc1d0512738ec7
Author: Swatantra Yadav <[email protected]>
AuthorDate: Sat Nov 7 00:09:09 2026 +0530
net/rpmsg: fix integer overflow in sendmsg and datagram truncation
1. In rpmsg_socket_get_iovlen(), iov_len values (size_t) were
accumulated into a uint32_t without overflow checking. If the sum
exceeded UINT32_MAX, it silently wrapped around. On 64-bit
platforms, individual iov_len values larger than UINT32_MAX were
also silently truncated. Fail with -EINVAL when the sum exceeds
MIN(SSIZE_MAX, UINT32_MAX), matching usrsock (commit 6e1126a)
and local (commit 56f37d5ba4).
2. In rpmsg_socket_send_continuous() (SOCK_STREAM), handle error
return from rpmsg_socket_get_iovlen() and return early.
3. In rpmsg_socket_send_single() (SOCK_DGRAM):
- Check len against conn->sendsize without addition overflow before
computing total = len + sizeof(uint32_t), returning -EMSGSIZE on
violation per POSIX sendmsg() semantics.
- Reject datagrams exceeding acquired TX buffer capacity (ipcsize)
with -EMSGSIZE and release the buffer, rather than silently
shortening total and len which transmitted truncated datagrams
and caused unsigned integer underflow.
- When concurrent senders reduce space below total under sendlock,
release the buffer and return -EAGAIN for nonblocking sockets,
or continue waiting on conn->sendsem for blocking sockets.
Assisted-by: Google Gemini:gemini-3.8-flash
Signed-off-by: Swatantra Yadav <[email protected]>
---
net/rpmsg/rpmsg_sockif.c | 106 +++++++++++++++++++++++++++++++++--------------
1 file changed, 74 insertions(+), 32 deletions(-)
diff --git a/net/rpmsg/rpmsg_sockif.c b/net/rpmsg/rpmsg_sockif.c
index a56b2ea330d..82498ca68e1 100644
--- a/net/rpmsg/rpmsg_sockif.c
+++ b/net/rpmsg/rpmsg_sockif.c
@@ -27,6 +27,7 @@
#include <nuttx/config.h>
#include <assert.h>
+#include <limits.h>
#include <nuttx/debug.h>
#include <poll.h>
#include <stdio.h>
@@ -989,14 +990,20 @@ static int rpmsg_socket_poll(FAR struct socket *psock,
return OK;
}
-static uint32_t rpmsg_socket_get_iovlen(FAR const struct iovec *buf,
- size_t iovcnt)
+static ssize_t rpmsg_socket_get_iovlen(FAR const struct iovec *buf,
+ size_t iovcnt)
{
- uint32_t len = 0;
+ size_t len = 0;
while (iovcnt--)
{
- len += (buf++)->iov_len;
+ if (buf->iov_len > MIN(SSIZE_MAX, UINT32_MAX) - len)
+ {
+ return -EINVAL;
+ }
+
+ len += buf->iov_len;
+ buf++;
}
return len;
@@ -1007,10 +1014,19 @@ static ssize_t rpmsg_socket_send_continuous(FAR struct
socket *psock,
size_t iovcnt, bool nonblock)
{
FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
- uint32_t len = rpmsg_socket_get_iovlen(buf, iovcnt);
+ ssize_t ret;
+ uint32_t len;
uint32_t written = 0;
uint32_t offset = 0;
- int ret = 0;
+
+ ret = rpmsg_socket_get_iovlen(buf, iovcnt);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ len = ret;
+ ret = 0;
while (written < len)
{
@@ -1100,59 +1116,85 @@ static ssize_t rpmsg_socket_send_single(FAR struct
socket *psock,
{
FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
FAR struct rpmsg_socket_data_s *msg;
- uint32_t len = rpmsg_socket_get_iovlen(buf, iovcnt);
- uint32_t total = len + sizeof(uint32_t);
+ FAR uint8_t *msgpos;
+ ssize_t ret;
+ uint32_t len;
+ uint32_t total;
uint32_t written = 0;
uint32_t ipcsize;
uint32_t space;
- FAR uint8_t *msgpos;
- int ret;
- if (total > conn->sendsize)
+ ret = rpmsg_socket_get_iovlen(buf, iovcnt);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ len = ret;
+ if (conn->sendsize < sizeof(uint32_t) ||
+ len > conn->sendsize - sizeof(uint32_t))
{
- return -EFBIG;
+ return -EMSGSIZE;
}
+ total = len + sizeof(uint32_t);
+
while (1)
{
nxmutex_lock(&conn->sendlock);
space = rpmsg_socket_get_space(conn);
nxmutex_unlock(&conn->sendlock);
- if (space >= total)
+ if (space < total)
{
- break;
+ if (nonblock)
+ {
+ return -EAGAIN;
+ }
+
+ ret = net_sem_timedwait(&conn->sendsem,
+ _SO_TIMEOUT(conn->sconn.s_sndtimeo));
+ if (!conn->ept.rdev || conn->unbind)
+ {
+ ret = -ECONNRESET;
+ }
+
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ continue;
}
- if (nonblock)
+ msg = rpmsg_get_tx_payload_buffer(&conn->ept, &ipcsize, true);
+ if (!msg)
{
- return -EAGAIN;
+ return -EINVAL;
}
- ret = net_sem_timedwait(&conn->sendsem,
- _SO_TIMEOUT(conn->sconn.s_sndtimeo));
- if (!conn->ept.rdev || conn->unbind)
+ if (ipcsize < sizeof(*msg) || total > ipcsize - sizeof(*msg))
{
- ret = -ECONNRESET;
+ rpmsg_release_tx_buffer(&conn->ept, msg);
+ return -EMSGSIZE;
}
- if (ret < 0)
+ nxmutex_lock(&conn->sendlock);
+ if (total > rpmsg_socket_get_space(conn))
{
- return ret;
+ nxmutex_unlock(&conn->sendlock);
+ rpmsg_release_tx_buffer(&conn->ept, msg);
+ if (nonblock)
+ {
+ return -EAGAIN;
+ }
+
+ continue;
}
- }
- msg = rpmsg_get_tx_payload_buffer(&conn->ept, &ipcsize, true);
- if (!msg)
- {
- return -EINVAL;
+ break;
}
- nxmutex_lock(&conn->sendlock);
- total = MIN(total, rpmsg_socket_get_space(conn));
- total = MIN(total, ipcsize - sizeof(*msg));
- len = total - sizeof(uint32_t);
-
/* SOCK_DGRAM need write len to buffer */
msg->cmd = RPMSG_SOCKET_CMD_DATA;