Commit 3ec7bb1935 for qemu.org

commit 3ec7bb19359c9368ac3e1556ffb156ab5f915ea3
Author: Eric Blake <eblake@redhat.com>
Date:   Tue Nov 10 09:53:59 2026 -0600

    nbd/server: Reject rather than assert on non-compliant BLOCK_STATUS

    The NBD spec is clear that a client must not send NBD_BLOCK_STATUS
    requests to a server if it did not negotiate any metacontexts with
    NBD_OPT_SET_META_CONTEXT for the current export.  However, if the
    non-compliant client uses NBD_OPT_EXTENDED_HEADERS and then passes in
    the relatively new NBD_CMD_FLAG_PAYLOAD_LEN flag alongside an
    inappropriate block status request, this was enough to trigger an
    assertion in qemu.  The assertion can also be tripped by initially
    requesting the context for one export, then using NBD_OPT_GO on a
    different export (nbd_check_meta_export() sets contexts.count to 0,
    but did not wipe contexts.exp). Forcing the client command to be
    rejected if contexts.count is 0 solves both triggers, and allows the
    assertion to still operate cleanly at a later location.

    If you do not use recommended practice to prevent unwanted clients
    from connecting to QEMU's NBD server, then any client can cause a
    denial of service with minimal effort.  However, with TLS and x509
    certs in place, an attacker must first chain in an attack to convince
    the client to send unwanted traffic, which is a factor in declaring
    this a lower-risk denial of service.

    Fixes: CVE-2026-124559
    Fixes: 2dcbb11b ("nbd/server: Add FLAG_PAYLOAD support to CMD_BLOCK_STATUS", v8.2.0)
    Reported-by: Feifan Qian <bea1e@proton.me>
    Reported-by: https://gitlab.com/qemu-project/qemu/-/work_items/3796
    CC: Haotian Jiang <jianghaotian.sunday@gmail.com>
    CC: qemu-stable@nongnu.org
    Signed-off-by: Eric Blake <eblake@redhat.com>
    Message-ID: <20261110155356.1520433-9-eblake@redhat.com>
    Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

diff --git a/nbd/server.c b/nbd/server.c
index e6c47f8c2e..8a01c27de0 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -2584,17 +2584,18 @@ nbd_co_block_status_payload_read(NBDClient *client, NBDRequest *request,
         return -EINVAL;
     }

-    assert(client->contexts.exp == client->exp);
     nr_bitmaps = client->exp->nr_export_bitmaps;
     request->contexts = g_new0(NBDMetaContexts, 1);
     request->contexts->exp = client->exp;

-    if (payload_len % sizeof(uint32_t) ||
+    if (!client->contexts.count ||
+        payload_len % sizeof(uint32_t) ||
         payload_len < sizeof(NBDBlockStatusPayload) ||
         payload_len > (sizeof(NBDBlockStatusPayload) +
                        sizeof(id) * client->contexts.count)) {
         goto skip;
     }
+    assert(client->contexts.exp == client->exp);

     buf = g_malloc(payload_len);
     if (nbd_read(client->ioc, buf, payload_len,