* [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928)
@ 2026-07-23 14:45 Stefan Hajnoczi
2026-07-23 14:45 ` [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929) Stefan Hajnoczi
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Stefan Hajnoczi @ 2026-07-23 14:45 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, Stefan Hajnoczi, Kevin Wolf, Hanna Reitz
The read-only dmg block driver can crash or leak information when it encounters
a malicious DMG file. The severity of these issues is low because the block
driver is used in qemu-img convert workflows where there is no sensitive
information to leak and crashing is a self-DoS.
See the individual patches for descriptions of the bugs.
Stefan Hajnoczi (3):
dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929)
dmg: refuse to open files with no chunks
dmg: reject inconsistent UDRW chunk sector count and length
(CVE-2026-65928)
block/dmg.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929)
2026-07-23 14:45 [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Stefan Hajnoczi
@ 2026-07-23 14:45 ` Stefan Hajnoczi
2026-07-24 6:41 ` Philippe Mathieu-Daudé
2026-07-24 14:27 ` Kevin Wolf
2026-07-23 14:45 ` [PATCH for-11.1 2/3] dmg: refuse to open files with no chunks Stefan Hajnoczi
` (2 subsequent siblings)
3 siblings, 2 replies; 8+ messages in thread
From: Stefan Hajnoczi @ 2026-07-23 14:45 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Stefan Hajnoczi, Kevin Wolf, Hanna Reitz, boy juju,
Tristan Madani
The binary search in search_chunk() uses s->n_chunks as the (inclusive)
upper bound. Chunk indices are in the right-open interval [0,
s->n_chunks) so it is wrong to search all the way up to s->n_chunks
rather than s->n_chunks - 1.
The worst case security scenario I can see is convincing a victim to
hotplug a malicious DMG file to a running guest, potentially causing
QEMU to crash when loading from memory beyond the end of s->sectors[] or
s->sectorscounts[]. This could be a denial of service.
Fixes: CVE-2026-65929
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3844
Reported-by: boy juju <agx1657748706@gmail.com>
Reported-by: Tristan Madani <tristan@talencesecurity.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/dmg.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/block/dmg.c b/block/dmg.c
index 33dcb3a3498..e325127d144 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -609,7 +609,10 @@ static inline int is_sector_in_chunk(BDRVDMGState *s,
static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
{
/* binary search */
- uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
+ uint32_t chunk1 = 0, chunk2 = s->n_chunks - 1, chunk3;
+ if (s->n_chunks == 0) {
+ goto err; /* should never happen */
+ }
while (chunk1 <= chunk2) {
chunk3 = (chunk1 + chunk2) / 2;
if (s->sectors[chunk3] > sector_num) {
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH for-11.1 2/3] dmg: refuse to open files with no chunks
2026-07-23 14:45 [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Stefan Hajnoczi
2026-07-23 14:45 ` [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929) Stefan Hajnoczi
@ 2026-07-23 14:45 ` Stefan Hajnoczi
2026-07-24 6:37 ` Philippe Mathieu-Daudé
2026-07-23 14:45 ` [PATCH for-11.1 3/3] dmg: reject inconsistent UDRW chunk sector count and length (CVE-2026-65928) Stefan Hajnoczi
2026-07-24 15:15 ` [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Kevin Wolf
3 siblings, 1 reply; 8+ messages in thread
From: Stefan Hajnoczi @ 2026-07-23 14:45 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-block, Stefan Hajnoczi, Kevin Wolf, Hanna Reitz,
Tristan Madani
The dmg block driver expects the disk image file to contain at least one
chunk. Refuse to open such files. This ensures that dmg block driver
state always has non-NULL s->sectors[] and related fields.
Note that the previous commit fixed the only known way to trigger a
crash. This patch is just for defense - let's avoid opening the file and
having NULL pointers in dmg block driver state.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4021
Reported-by: Tristan Madani <tristan@talencesecurity.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/dmg.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/block/dmg.c b/block/dmg.c
index e325127d144..6f8120e0338 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -559,6 +559,12 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
+ /* There must be at least one chunk */
+ if (s->n_chunks == 0) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
/* initialize zlib engine */
s->compressed_chunk = qemu_try_blockalign(bs->file->bs,
ds.max_compressed_size + 1);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH for-11.1 3/3] dmg: reject inconsistent UDRW chunk sector count and length (CVE-2026-65928)
2026-07-23 14:45 [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Stefan Hajnoczi
2026-07-23 14:45 ` [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929) Stefan Hajnoczi
2026-07-23 14:45 ` [PATCH for-11.1 2/3] dmg: refuse to open files with no chunks Stefan Hajnoczi
@ 2026-07-23 14:45 ` Stefan Hajnoczi
2026-07-24 15:15 ` [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Kevin Wolf
3 siblings, 0 replies; 8+ messages in thread
From: Stefan Hajnoczi @ 2026-07-23 14:45 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, Stefan Hajnoczi, Kevin Wolf, Hanna Reitz, boy juju
The chunk metadata contains both:
- Sector count: number of 512-byte sectors in the virtual disk
- Length: number of bytes in the image file
The UDRW chunk type indicates uncompressed data that can be accessed
directly. The code is missing input validation to verify that sector
count is consistent with length.
If sector count is larger than length, then read requests can access
beyond the end of the s->uncompressed_chunk buffer. This is an
out-of-bounds heap access that could lead to a crash or an information
leak.
While we're at it, also zero the end of the last sector when length is
unaligned. This prevents information leaks from the
s->uncompressed_chunk buffer.
Fixes: CVE-2026-65928
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3846
Reported-by: boy juju <agx1657748706@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/dmg.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/block/dmg.c b/block/dmg.c
index 6f8120e0338..5d7d3b8901f 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -312,6 +312,21 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
goto fail;
}
+ /*
+ * Uncompressed chunk length must match sector count. Compressed chunks
+ * are validated during dmg_read_chunk() since the uncompressed size is
+ * not known ahead of time.
+ */
+ if (s->types[i] == UDRW) {
+ if (s->sectorcounts[i] != DIV_ROUND_UP(s->lengths[i], 512)) {
+ error_report("length %" PRIu64 " for chunk %" PRIu32
+ " is inconsistent with sector count %" PRIu64,
+ s->lengths[i], i, s->sectorcounts[i]);
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
update_max_chunk_size(s, i, &ds->max_compressed_size,
&ds->max_sectors_per_chunk);
offset += 40;
@@ -722,6 +737,16 @@ dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
if (ret < 0) {
return -1;
}
+
+ /*
+ * Zero the unread part of the last sector when chunk length is
+ * unaligned to avoid exposing uninitialized memory. Valid image
+ * files may never hit this case, but cover it to be safe.
+ */
+ if (s->lengths[chunk] & 511) {
+ size_t trailing_bytes = 512 - (s->lengths[chunk] & 511);
+ memset(s->uncompressed_chunk + s->lengths[chunk], 0, trailing_bytes);
+ }
break;
case UDZE: /* zeros */
case UDIG: /* ignore */
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH for-11.1 2/3] dmg: refuse to open files with no chunks
2026-07-23 14:45 ` [PATCH for-11.1 2/3] dmg: refuse to open files with no chunks Stefan Hajnoczi
@ 2026-07-24 6:37 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 8+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-24 6:37 UTC (permalink / raw)
To: Stefan Hajnoczi, qemu-devel
Cc: qemu-block, Kevin Wolf, Hanna Reitz, Tristan Madani
On 23/7/26 16:45, Stefan Hajnoczi wrote:
> The dmg block driver expects the disk image file to contain at least one
> chunk. Refuse to open such files. This ensures that dmg block driver
> state always has non-NULL s->sectors[] and related fields.
>
> Note that the previous commit fixed the only known way to trigger a
> crash. This patch is just for defense - let's avoid opening the file and
> having NULL pointers in dmg block driver state.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4021
> Reported-by: Tristan Madani <tristan@talencesecurity.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> block/dmg.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/block/dmg.c b/block/dmg.c
> index e325127d144..6f8120e0338 100644
> --- a/block/dmg.c
> +++ b/block/dmg.c
> @@ -559,6 +559,12 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
> goto fail;
> }
>
> + /* There must be at least one chunk */
dmg_read_mish_block indirectly updates s->n_chunks via the
dmg_read_resource_fork / dmg_read_plist_xml calls. Both
access BDRVDMGState @s via bs->opaque. OK then.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> + if (s->n_chunks == 0) {
> + ret = -EINVAL;
> + goto fail;
> + }
> +
> /* initialize zlib engine */
> s->compressed_chunk = qemu_try_blockalign(bs->file->bs,
> ds.max_compressed_size + 1);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929)
2026-07-23 14:45 ` [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929) Stefan Hajnoczi
@ 2026-07-24 6:41 ` Philippe Mathieu-Daudé
2026-07-24 14:27 ` Kevin Wolf
1 sibling, 0 replies; 8+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-24 6:41 UTC (permalink / raw)
To: Stefan Hajnoczi, qemu-devel
Cc: qemu-block, Kevin Wolf, Hanna Reitz, boy juju, Tristan Madani
On 23/7/26 16:45, Stefan Hajnoczi wrote:
> The binary search in search_chunk() uses s->n_chunks as the (inclusive)
> upper bound. Chunk indices are in the right-open interval [0,
> s->n_chunks) so it is wrong to search all the way up to s->n_chunks
> rather than s->n_chunks - 1.
>
> The worst case security scenario I can see is convincing a victim to
> hotplug a malicious DMG file to a running guest, potentially causing
> QEMU to crash when loading from memory beyond the end of s->sectors[] or
> s->sectorscounts[]. This could be a denial of service.
>
> Fixes: CVE-2026-65929
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3844
> Reported-by: boy juju <agx1657748706@gmail.com>
> Reported-by: Tristan Madani <tristan@talencesecurity.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> block/dmg.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/block/dmg.c b/block/dmg.c
> index 33dcb3a3498..e325127d144 100644
> --- a/block/dmg.c
> +++ b/block/dmg.c
> @@ -609,7 +609,10 @@ static inline int is_sector_in_chunk(BDRVDMGState *s,
> static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
> {
> /* binary search */
> - uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
> + uint32_t chunk1 = 0, chunk2 = s->n_chunks - 1, chunk3;
> + if (s->n_chunks == 0) {
> + goto err; /* should never happen */
> + }
> while (chunk1 <= chunk2) {
> chunk3 = (chunk1 + chunk2) / 2;
> if (s->sectors[chunk3] > sector_num) {
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Alternatively avoiding the assignations:
-- >8 --
diff --git a/block/dmg.c b/block/dmg.c
index 33dcb3a3498..85edfae145b 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -609,8 +609,12 @@ static inline int is_sector_in_chunk(BDRVDMGState *s,
static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
{
/* binary search */
- uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
- while (chunk1 <= chunk2) {
+ uint32_t chunk1, chunk2, chunk3;
+
+ if (s->n_chunks == 0) {
+ goto err; /* should never happen */
+ }
+ for (chunk1 = 0, chunk2 = s->n_chunks - 1; chunk1 <= chunk2; ) {
chunk3 = (chunk1 + chunk2) / 2;
if (s->sectors[chunk3] > sector_num) {
if (chunk3 == 0) {
---
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929)
2026-07-23 14:45 ` [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929) Stefan Hajnoczi
2026-07-24 6:41 ` Philippe Mathieu-Daudé
@ 2026-07-24 14:27 ` Kevin Wolf
1 sibling, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2026-07-24 14:27 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: qemu-devel, qemu-block, Hanna Reitz, boy juju, Tristan Madani
Am 23.07.2026 um 16:45 hat Stefan Hajnoczi geschrieben:
> The binary search in search_chunk() uses s->n_chunks as the (inclusive)
> upper bound. Chunk indices are in the right-open interval [0,
> s->n_chunks) so it is wrong to search all the way up to s->n_chunks
> rather than s->n_chunks - 1.
>
> The worst case security scenario I can see is convincing a victim to
> hotplug a malicious DMG file to a running guest, potentially causing
> QEMU to crash when loading from memory beyond the end of s->sectors[] or
> s->sectorscounts[]. This could be a denial of service.
>
> Fixes: CVE-2026-65929
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3844
> Reported-by: boy juju <agx1657748706@gmail.com>
> Reported-by: Tristan Madani <tristan@talencesecurity.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> block/dmg.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/block/dmg.c b/block/dmg.c
> index 33dcb3a3498..e325127d144 100644
> --- a/block/dmg.c
> +++ b/block/dmg.c
> @@ -609,7 +609,10 @@ static inline int is_sector_in_chunk(BDRVDMGState *s,
> static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
> {
> /* binary search */
> - uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
> + uint32_t chunk1 = 0, chunk2 = s->n_chunks - 1, chunk3;
> + if (s->n_chunks == 0) {
> + goto err; /* should never happen */
> + }
> while (chunk1 <= chunk2) {
> chunk3 = (chunk1 + chunk2) / 2;
> if (s->sectors[chunk3] > sector_num) {
Fair enough to keep the fix minimal here, but is there any justification
for manually implementing binary search instead of using bsearch()? If
not, this could be a follow-up cleanup.
Kevin
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928)
2026-07-23 14:45 [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Stefan Hajnoczi
` (2 preceding siblings ...)
2026-07-23 14:45 ` [PATCH for-11.1 3/3] dmg: reject inconsistent UDRW chunk sector count and length (CVE-2026-65928) Stefan Hajnoczi
@ 2026-07-24 15:15 ` Kevin Wolf
3 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2026-07-24 15:15 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: qemu-devel, qemu-block, Hanna Reitz
Am 23.07.2026 um 16:45 hat Stefan Hajnoczi geschrieben:
> The read-only dmg block driver can crash or leak information when it encounters
> a malicious DMG file. The severity of these issues is low because the block
> driver is used in qemu-img convert workflows where there is no sensitive
> information to leak and crashing is a self-DoS.
>
> See the individual patches for descriptions of the bugs.
Thanks, applied to the block branch.
Kevin
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-07-24 15:16 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 14:45 [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Stefan Hajnoczi
2026-07-23 14:45 ` [PATCH for-11.1 1/3] dmg: fix out-of-bounds load in search_chunk() (CVE-2026-65929) Stefan Hajnoczi
2026-07-24 6:41 ` Philippe Mathieu-Daudé
2026-07-24 14:27 ` Kevin Wolf
2026-07-23 14:45 ` [PATCH for-11.1 2/3] dmg: refuse to open files with no chunks Stefan Hajnoczi
2026-07-24 6:37 ` Philippe Mathieu-Daudé
2026-07-23 14:45 ` [PATCH for-11.1 3/3] dmg: reject inconsistent UDRW chunk sector count and length (CVE-2026-65928) Stefan Hajnoczi
2026-07-24 15:15 ` [PATCH for-11.1 0/3] dmg: add missing input validation (CVE-2026-65929 & CVE-2026-65928) Kevin Wolf
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.