Commit 24dbf7e24d for qemu.org

commit 24dbf7e24d83d50237c7ec5166a02a703b1359f3
Author: Peter Xu <peterx@redhat.com>
Date:   Thu Aug 20 16:03:19 2026 -0400

    migration/rdma: Sanity check RDMA_CONTROL_REGISTER_REQUEST on buflen

    RDMA header supports head.repeat on RDMA_CONTROL_REGISTER_REQUEST, which
    can include >1 memory registrations.  The current code did check over
    head.repeat to guard against RDMA_CONTROL_MAX_COMMANDS_PER_MESSAGE, however
    it didn't further check the buffer size (head.len) to make sure the
    received data is large enough to include the repeated entries.  Check it.

    This is almost only to harden this piece of code, in reality on source side
    QEMU never uses repeat>1..  However since it's a protocol, still keep it.
    Check the buffer size instead.

    In case it's not obvious to new RDMA readers: head.len should be the size
    RDMA has last received, as qemu_rdma_exchange_get_response() checked on it
    against byte_len (which was further fetched from ibv_wc.byte_len in
    qemu_rdma_poll()).

    Reported-by: Tristan (@TristanInSec)
    Closes: https://gitlab.com/qemu-project/qemu/-/work_items/4028
    Reviewed-by: Jinpu Wang <jinpu.wang@cloud.ionos.com>
    Signed-off-by: Peter Xu <peterx@redhat.com>
    Reviewed-by: Fabiano Rosas <farosas@suse.de>
    Reviewed-by: Jack Wang <jinpu.wang@cloud.ionos.com>
    Signed-off-by: Fabiano Rosas <farosas@suse.de>

diff --git a/migration/rdma.c b/migration/rdma.c
index 683c24ba4d..f7356e759f 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -3360,6 +3360,14 @@ int rdma_registration_handle(QEMUFile *f)
             reg_resp.repeat = head.repeat;
             registers = (RDMARegister *) rdma->wr_data[idx].control_curr;

+            /* Making sure the register buffers to read are valid */
+            if (head.len != head.repeat * sizeof(RDMARegister)) {
+                error_report("%s: Invalid RDMA_CONTROL_REGISTER_REQUEST "
+                             "(head.repeat=%"PRIu32", head.len=%"PRIu32")",
+                             __func__, head.repeat, head.len);
+                goto err;
+            }
+
             for (int count = 0; count < head.repeat; count++) {
                 uint64_t chunk;
                 uint8_t *chunk_start, *chunk_end;