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;

Reply via email to