Commit fe2cbdda07 for qemu.org

commit fe2cbdda07c20c3b55e91522113b10a5d70ac0b3
Author: Peter Maydell <peter.maydell@linaro.org>
Date:   Tue Nov 3 14:35:13 2026 +0000

    block/vmdk: Avoid reading off the end of descriptor memory

    In vmdk_parent_open() and vmdk_read_cid(), we read DESC_SIZE bytes
    from the image file into a malloc'd buffer, and then look through it
    for a keyword using strstr().  If found, we skip past the keyword and
    attempt to parse a value from the next part of the buffer.  However,
    we failed to check whether the end of the keyword is right at the end
    of the buffer, and so a malicious image can cause us to read off the
    end when parsing the value part.

    Check for this condition before attempting to parse the value.

    The worst case here is that the image causes us to read some junk
    from the heap into the BlockDriverState backing_file and
    auto_backing_file fields; the image could control those anyway, and
    it's unlikely that this heap data could e.g. be leaked to the guest.

    Cc: qemu-stable@nongnu.org
    Reported-by: router0mail <https://gitlab.com/router0mail>
    Fixes: 5f4da8c0f3736b2 ("New multiple snapshot support for VMDK")
    Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4571
    Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
    Message-ID: <20261103143516.2182626-3-peter.maydell@linaro.org>
    Reviewed-by: Kevin Wolf <kwolf@redhat.com>
    Signed-off-by: Kevin Wolf <kwolf@redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 86059e1fa0..6e4e0423dc 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -337,6 +337,10 @@ vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid)
         goto out;
     }
     p_name += cid_str_size;
+    if (p_name >= desc + DESC_SIZE) {
+        ret = -EINVAL;
+        goto out;
+    }
     if (sscanf(p_name, "%" SCNx32, &cid) != 1) {
         ret = -EINVAL;
         goto out;
@@ -508,6 +512,10 @@ static int GRAPH_RDLOCK vmdk_parent_open(BlockDriverState *bs)
         char *end_name;

         p_name += sizeof("parentFileNameHint") + 1;
+        if (p_name >= desc + DESC_SIZE + 1) {
+            ret = -EINVAL;
+            goto out;
+        }
         end_name = strchr(p_name, '\"');
         if (end_name == NULL) {
             ret = -EINVAL;