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 8d69e104f1e openamp: Do not trust buffer and header lengths written by 
the remote.
8d69e104f1e is described below

commit 8d69e104f1e4d7e166b79068c6ee3c57fc150c70
Author: Lourens Naude <[email protected]>
AuthorDate: Thu Oct 8 22:07:42 2026 +0100

    openamp: Do not trust buffer and header lengths written by the remote.
    
    rpmsg_virtio on the driver side takes the TX buffer length from
    used->len and hands rpmsg_hdr.len to endpoint callbacks unchecked; both
    are written by the remote.  A used->len of 0 turned into a 4 GB payload
    capacity and reset the chip on the RT1176, and a header length larger
    than the buffer let callbacks read past it.  Patch 0020 fixes the
    driver-side TX size to h2r_buf_size, clamps the RX length to
    r2h_buf_size and drops a message whose header does not fit before any
    callback runs.  Found with a bare-metal CM4 remote on the RT1170 RPTUN
    backend; applies to every rptun backend.
    
    Assisted-by: Claude:claude-fable-5-1
    Signed-off-by: Lourens Naude <[email protected]>
---
 ...o-not-trust-lengths-written-by-the-remote.patch | 62 ++++++++++++++++++++++
 openamp/open-amp.defs                              |  1 +
 2 files changed, 63 insertions(+)

diff --git 
a/openamp/0020-rpmsg_virtio-do-not-trust-lengths-written-by-the-remote.patch 
b/openamp/0020-rpmsg_virtio-do-not-trust-lengths-written-by-the-remote.patch
new file mode 100644
index 00000000000..d742543b250
--- /dev/null
+++ b/openamp/0020-rpmsg_virtio-do-not-trust-lengths-written-by-the-remote.patch
@@ -0,0 +1,62 @@
+From 6710e18a7b9631f5da2bdc8010ba0a79ac0e4317 Mon Sep 17 00:00:00 2001
+From: Lourens Naude <[email protected]>
+Date: Thu, 8 Oct 2026 22:14:33 +0100
+Subject: [PATCH 20/20] rpmsg_virtio: do not trust lengths written by the
+ remote
+
+On the driver side every TX buffer is h2r_buf_size long and every RX
+buffer r2h_buf_size long; used->len and rpmsg_hdr.len come from the
+remote.  A used->len of 0 turned into a 4 GB payload capacity, a header
+length larger than the buffer let endpoint callbacks read past it.
+
+Signed-off-by: Lourens Naude <[email protected]>
+---
+ lib/rpmsg/rpmsg_virtio.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
+index 9913d87..45783ab 100644
+--- a/lib/rpmsg/rpmsg_virtio.c
++++ open-amp/lib/rpmsg/rpmsg_virtio.c
+@@ -198,9 +198,11 @@ static void *rpmsg_virtio_get_tx_buffer(struct 
rpmsg_virtio_device *rvdev,
+               if (!data && rvdev->svq->vq_free_cnt) {
+                       data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool,
+                                       rvdev->config.h2r_buf_size);
+-                      *len = rvdev->config.h2r_buf_size;
+                       *idx = 0;
+               }
++              /* used->len was written by the remote; the buffer is ours */
++              if (data)
++                      *len = rvdev->config.h2r_buf_size;
+       } else if (VIRTIO_ROLE_IS_DEVICE(rvdev->vdev)) {
+               data = virtqueue_get_first_avail_buffer(rvdev->svq, idx, len);
+       }
+@@ -227,6 +229,9 @@ static void *rpmsg_virtio_get_rx_buffer(struct 
rpmsg_virtio_device *rvdev,
+ 
+       if (VIRTIO_ROLE_IS_DRIVER(rvdev->vdev)) {
+               data = virtqueue_get_buffer(rvdev->rvq, len, idx);
++              /* used->len was written by the remote; never exceed our buffer 
*/
++              if (data && *len > rvdev->config.r2h_buf_size)
++                      *len = rvdev->config.r2h_buf_size;
+               *last = virtqueue_nused(rvdev->rvq) == 0;
+       }
+ 
+@@ -578,7 +583,14 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq)
+               rp_hdr->reserved = idx;
+ 
+               /* Get the channel node from the remote device channels list. */
+-              ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst);
++              /* The header was written by the remote: a payload length that
++               * does not fit the buffer is dropped without a callback.
++               */
++              if (len >= sizeof(*rp_hdr) &&
++                  rp_hdr->len <= len - sizeof(*rp_hdr))
++                      ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst);
++              else
++                      ept = NULL;
+               rpmsg_ept_incref(ept);
+               RPMSG_BUF_HELD_INC(rp_hdr);
+               metal_mutex_release(&rdev->lock);
+-- 
+2.53.0
+
diff --git a/openamp/open-amp.defs b/openamp/open-amp.defs
index 36c81fed13d..4ad12ce949b 100644
--- a/openamp/open-amp.defs
+++ b/openamp/open-amp.defs
@@ -85,6 +85,7 @@ open-amp.zip:
        $(Q) patch -p0 < 
0017-lib-virtio-virtqueue-change-the-virtqueue-dump-log-l.patch
        $(Q) patch -p0 < 
0018-lib-rpmsg-add-priority-support-for-rpmsg-endpoint.patch
        $(Q) patch -p0 < 
0019-rpmsg-Add-VIRTIO_RPMSG_F_BUFADDR-to-support-specify-.patch
+       $(Q) patch -p0 < 
0020-rpmsg_virtio-do-not-trust-lengths-written-by-the-remote.patch
 
 .openamp_headers: open-amp.zip
 else

Reply via email to