All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, richard.henderson@linaro.org, qemu-devel@nongnu.org
Subject: [PULL 11/11] block/vhdx: Prevent out-of-bounds BAT accesses with malicious vhdx files
Date: Mon,  9 Nov 2026 17:45:33 +0100	[thread overview]
Message-ID: <20261109164533.293487-12-kwolf@redhat.com> (raw)
In-Reply-To: <20261109164533.293487-1-kwolf@redhat.com>

From: Thomas Huth <thuth@redhat.com>

virtual_disk_size is read directly from a VHDX image's metadata region
and never checked for sane sizes.  The 64 TiB limit (VHDX_MAX_IMAGE_SIZE)
is only enforced in vhdx_co_create(), so it limits images QEMU creates
but never images QEMU opens.

Without the bound, vhdx_calc_bat_entries() computes the block count
into a uint32_t, so a huge image size gets truncated and the BAT is
undersized relative to total_sectors.
vhdx_block_translate() then converts sector numbers into BAT indices
with no bounds check, allowing out-of-bounds access on the BAT array
from both the read and write paths.

To fix the problem, add a VHDX_MAX_IMAGE_SIZE check to vhdx_parse_metadata()
so images opened for reading are subject to the same limit as images
created by QEMU.
With this limit, the calculation in vhdx_calc_bat_entries() cannot get
truncated anymore (block_size is at least 1 MiB):

 VHDX_MAX_IMAGE_SIZE / block_size = 64 TiB / 1 MiB = 64 MiB

... and 64 MiB fit nicely into 32 bits.

To be really on the safe side, let's also add an assertion in
vhdx_block_translate() to catch accesses that exceeds the allocated
entry count.

Buglink: https://gitlab.com/qemu-project/qemu/-/work_items/3762
Reported-by: Daniel Wade <danjwade95@gmail.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4470
Reported-by: Mayank Jangid (OpenSec)
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4487
Reported-by: Ken Hsu, Royce Lu, and Bo Qu of Palo Alto Networks
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4638
Reported-by: Thai Duong (Calif.io)
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4733
Reported-by: Xiang Chen
Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20261023130023.539252-1-thuth@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vhdx.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/block/vhdx.c b/block/vhdx.c
index c16e4a00c8d..8013a90a1a4 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -815,6 +815,11 @@ vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
     }
 
     s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
+    if (s->virtual_disk_size > VHDX_MAX_IMAGE_SIZE) {
+        ret = -EFBIG;
+        goto exit;
+    }
+
     s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
     s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
 
@@ -1149,6 +1154,7 @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num,
 
     sinfo->bytes_avail = sinfo->sectors_avail << s->logical_sector_size_bits;
 
+    assert(sinfo->bat_idx < s->bat_entries);
     sinfo->file_offset = s->bat[sinfo->bat_idx] & VHDX_BAT_FILE_OFF_MASK;
 
     sinfo->block_offset = block_offset << s->logical_sector_size_bits;
-- 
2.56.0



  parent reply	other threads:[~2026-11-09 16:48 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 16:45 [PULL 00/11] Block layer patches Kevin Wolf
2026-11-09 16:45 ` [PULL 01/11] iotests: add --quiet arg to hide env variable dump Kevin Wolf
2026-11-09 16:45 ` [PULL 02/11] block/vmdk: Avoid assertion if image file has no extents Kevin Wolf
2026-11-09 16:45 ` [PULL 03/11] block/vmdk: Avoid reading off the end of descriptor memory Kevin Wolf
2026-11-09 16:45 ` [PULL 04/11] block/vmdk: Use larger types for byte counts in vmdk_read_extent() Kevin Wolf
2026-11-09 16:45 ` [PULL 05/11] block/vmdk: Reject a zero cluster_sectors parameter Kevin Wolf
2026-11-09 16:45 ` [PULL 06/11] block/vmdk: Avoid overflowing multiplication in vmdk_open_vmdk4() Kevin Wolf
2026-11-09 16:45 ` [PULL 07/11] block: add missing coroutine_fn annotations Kevin Wolf
2026-11-09 16:45 ` [PULL 08/11] iotests/290: add test case to check 'discard-no-unref' option behavior Kevin Wolf
2026-11-09 16:45 ` [PULL 09/11] qcow2: fix snapshot data corruption with discard-no-unref=on Kevin Wolf
2026-11-09 16:45 ` [PULL 10/11] iotests/290: add 'discard' and 'write -z -u' case with a snapshot Kevin Wolf
2026-11-09 16:45 ` Kevin Wolf [this message]
2026-11-09 20:53 ` [PULL 00/11] Block layer patches Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261109164533.293487-12-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.