[PATCH v2] hw/display: refine upper limit for offset value in assert check

2024-12-12 Thread gerben
From: Denis Rastyogin 

Accessing an element of the s->core_registers array,
which has a size of 236 (0x3AC), may lead to a buffer overflow
if the 'offset' index exceeds the valid range, potentially
reaching values up to 5139 (0x504C >> 2). Therefore, the bounds
check has been extended to DP_CORE_REG_ARRAY_SIZE (0x3B0 >> 2).
This change addresses a potential vulnerability by ensuring
the offset stays within the valid range before writing data.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Reported-by: David Meliksetyan 
Signed-off-by: Denis Rastyogin 
---
 hw/display/xlnx_dp.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 6ab2335499..3f1f5d81bd 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -896,7 +896,11 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, 
uint64_t value,
 xlnx_dp_update_irq(s);
 break;
 default:
-assert(offset <= (0x504C >> 2));
+/*
+ * Check to ensure the offset is within the bounds of
+ * the core_registers[] array.
+*/
+assert(offset < DP_CORE_REG_ARRAY_SIZE);
 s->core_registers[offset] = value;
 break;
 }
-- 
2.42.2




[PATCH] target/arm: remove redundant code

2024-12-12 Thread gerben
From: Denis Rastyogin 

This call is redundant as it only retrieves a value that is not used further.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Denis Rastyogin 
---
 target/arm/vfp_helper.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
index 62638d2b1f..f020c3c34b 100644
--- a/target/arm/vfp_helper.c
+++ b/target/arm/vfp_helper.c
@@ -1095,8 +1095,6 @@ float64 HELPER(rintd)(float64 x, void *fp_status)
 
 ret = float64_round_to_int(x, fp_status);
 
-new_flags = get_float_exception_flags(fp_status);
-
 /* Suppress any inexact exceptions the conversion produced */
 if (!(old_flags & float_flag_inexact)) {
 new_flags = get_float_exception_flags(fp_status);
-- 
2.42.2




[PATCH] hw/display: refine upper limit for offset value in assert check

2024-12-12 Thread gerben
From: Denis Rastyogin 

Accessing an element of the s->core_registers array
with a size of 236 (0x3AC) may lead to a buffer overflow,
as the index 'offset' can exceed the valid range and reach values
up to 5139 (0x504C >> 2). This change addresses
a potential vulnerability when writing data.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Reported-by: David Meliksetyan 
Signed-off-by: Denis Rastyogin 
---
 hw/display/xlnx_dp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 6ab2335499..69ccc7ccc2 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -743,6 +743,7 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, 
uint64_t value,
 DPRINTF("core write @%" PRIx64 " = 0x%8.8" PRIX64 "\n", offset, value);
 
 offset = offset >> 2;
+assert(offset <= (0x3AC >> 2));
 
 switch (offset) {
 /*
@@ -896,7 +897,6 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, 
uint64_t value,
 xlnx_dp_update_irq(s);
 break;
 default:
-assert(offset <= (0x504C >> 2));
 s->core_registers[offset] = value;
 break;
 }
-- 
2.42.2




[PATCH] parallels: fix ext_off assertion failure due to overflow

2024-12-12 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

When ph.ext_off has a sufficiently large value, the operation
le64_to_cpu(ph.ext_off) << BDRV_SECTOR_BITS in
parallels_read_format_extension() can cause an overflow in int64_t.
This overflow triggers the assert(ext_off > 0)
check in block/parallels-ext.c: parallels_read_format_extension(), 
leading to a crash.

This commit adds a check to prevent overflow when shifting ph.ext_off
by BDRV_SECTOR_BITS, ensuring that the value remains within a valid range.

Reported-by: Leonid Reviakin 
Signed-off-by: Denis Rastyogin 
---
 block/parallels.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/block/parallels.c b/block/parallels.c
index 9205a0864f..8f2b58e1c9 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -1298,6 +1298,10 @@ static int parallels_open(BlockDriverState *bs, QDict 
*options, int flags,
 error_setg(errp, "Catalog too large");
 return -EFBIG;
 }
+if (le64_to_cpu(ph.ext_off) >= (INT64_MAX >> BDRV_SECTOR_BITS)) {
+error_setg(errp, "Invalid image: Too big offset");
+return -EFBIG;
+}
 
 size = bat_entry_off(s->bat_size);
 s->header_size = ROUND_UP(size, bdrv_opt_mem_align(bs->file->bs));
-- 
2.42.2




[PATCH] parallels: fix ext_off assertion failure due to overflow

2024-12-12 Thread gerben
Hi,
If necessary, I can provide an image file to reproduce the error.

Regards,
Denis Rastyogin





[PATCH] target/arm/tcg: fix potential integer overflow in iwmmxt_macuw()

2024-12-12 Thread gerben
From: Denis Rastyogin 

The function iwmmxt_macuw() could potentially cause an integer
overflow when summing up four 32-bit multiplications.
This occurs because the intermediate results may exceed the 32-bit
range before being cast to uint64_t. The fix ensures each
multiplication is explicitly cast to uint64_t prior to summation,
preventing potential issues and ensuring correctness.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Denis Sergeev 
Signed-off-by: Denis Rastyogin 
---
 target/arm/tcg/iwmmxt_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/tcg/iwmmxt_helper.c b/target/arm/tcg/iwmmxt_helper.c
index 610b1b2103..19c709655e 100644
--- a/target/arm/tcg/iwmmxt_helper.c
+++ b/target/arm/tcg/iwmmxt_helper.c
@@ -140,7 +140,7 @@ uint64_t HELPER(iwmmxt_macsw)(uint64_t a, uint64_t b)
 
 uint64_t HELPER(iwmmxt_macuw)(uint64_t a, uint64_t b)
 {
-#define MACU(SHR) ( \
+#define MACU(SHR) (uint64_t)( \
 (uint32_t) ((a >> SHR) & 0x) * \
 (uint32_t) ((b >> SHR) & 0x))
 return MACU(0) + MACU(16) + MACU(32) + MACU(48);
-- 
2.42.2




[PATCH v3] hw/display: refine upper limit for offset value in assert check

2024-12-12 Thread gerben
From: Denis Rastyogin 

Accessing an element of the s->core_registers array,
which has a size of 236 (0x3AC), may lead to a buffer overflow
if the 'offset' index exceeds the valid range, potentially
reaching values up to 5139 (0x504C >> 2). The bounds check
has been extended to DP_CORE_REG_ARRAY_SIZE (0x3B0 >> 2)
to ensure the offset remains within the valid range before writing data.

The memory region is registered to match the size of
the core_registers array. This ensures that the guest cannot issue
an out-of-bounds write. Therefore, using `assert` remains appropriate
to catch internal violations.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Reported-by: David Meliksetyan 
Signed-off-by: Denis Rastyogin 
---
 hw/display/xlnx_dp.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 6ab2335499..3f1f5d81bd 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -896,7 +896,11 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, 
uint64_t value,
 xlnx_dp_update_irq(s);
 break;
 default:
-assert(offset <= (0x504C >> 2));
+/*
+ * Check to ensure the offset is within the bounds of
+ * the core_registers[] array.
+*/
+assert(offset < DP_CORE_REG_ARRAY_SIZE);
 s->core_registers[offset] = value;
 break;
 }
-- 
2.42.2




[PATCH] target/mips: fix possible int overflow

2025-01-24 Thread gerben
From: Denis Rastyogin 

Fix possible overflow in 1 << (DF_BITS(df) - 2) when DF_BITS(df) 
is 64 by using a 64-bit integer for the shift operation.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Reported-by: Dmitriy Fedin 
Signed-off-by: Denis Rastyogin 
---
 target/mips/tcg/msa_helper.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index 1d40383ca4..5ced3168b4 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -5577,7 +5577,7 @@ static inline int64_t msa_mulr_q_df(uint32_t df, int64_t 
arg1, int64_t arg2)
 {
 int64_t q_min = DF_MIN_INT(df);
 int64_t q_max = DF_MAX_INT(df);
-int64_t r_bit = 1 << (DF_BITS(df) - 2);
+int64_t r_bit = 1LL << (DF_BITS(df) - 2);
 
 if (arg1 == q_min && arg2 == q_min) {
 return q_max;
@@ -5685,7 +5685,7 @@ static inline int64_t msa_maddr_q_df(uint32_t df, int64_t 
dest, int64_t arg1,
 
 int64_t q_max = DF_MAX_INT(df);
 int64_t q_min = DF_MIN_INT(df);
-int64_t r_bit = 1 << (DF_BITS(df) - 2);
+int64_t r_bit = 1LL << (DF_BITS(df) - 2);
 
 q_prod = arg1 * arg2;
 q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod + r_bit) >> (DF_BITS(df) - 
1);
@@ -5700,7 +5700,7 @@ static inline int64_t msa_msubr_q_df(uint32_t df, int64_t 
dest, int64_t arg1,
 
 int64_t q_max = DF_MAX_INT(df);
 int64_t q_min = DF_MIN_INT(df);
-int64_t r_bit = 1 << (DF_BITS(df) - 2);
+int64_t r_bit = 1LL << (DF_BITS(df) - 2);
 
 q_prod = arg1 * arg2;
 q_ret = ((dest << (DF_BITS(df) - 1)) - q_prod + r_bit) >> (DF_BITS(df) - 
1);
-- 
2.42.2




[PATCH] qcow2: fix null pointer dereference in crypto block

2025-03-18 Thread gerben
You can reproduce this issue by running ./qemu-img info segv. 
The segv file used for reproduction can be found here: 
https://github.com/Gerben100/reproduce_qemu-img_error



[PATCH] qemu-img: fix division by zero in bench_cb() for zero-sized images

2025-03-18 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

This commit fixes a division by zero error in the bench_cb() function
that occurs when using the bench command with a zero-sized image.

The issue arises because b->image_size can be zero, leading to a
division by zero in the modulo operation (b->offset %= b->image_size).
This patch adds a check for b->image_size == 0 and resets b->offset
to 0 in such cases, preventing the error.

Signed-off-by: Denis Rastyogin 
---
 qemu-img.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/qemu-img.c b/qemu-img.c
index 89c93c1eb5..2044c22a4c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4488,7 +4488,11 @@ static void bench_cb(void *opaque, int ret)
  */
 b->in_flight++;
 b->offset += b->step;
-b->offset %= b->image_size;
+if (b->image_size == 0) {
+b->offset = 0;
+} else {
+b->offset %= b->image_size;
+}
 if (b->write) {
 acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
 } else {
-- 
2.42.2




[PATCH] qcow2: fix null pointer dereference in crypto block

2025-03-18 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

The qcow2_refresh_limits() is missing a check
for the s->crypto pointer, which can lead to
a null pointer dereference. This commit adds the necessary check.

Reported-by: Leonid Reviakin 
Signed-off-by: Denis Rastyogin 
---
 block/qcow2.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/block/qcow2.c b/block/qcow2.c
index dd6bcafbd8..55861a285a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1978,6 +1978,10 @@ static void qcow2_refresh_limits(BlockDriverState *bs, 
Error **errp)
 
 if (bs->encrypted) {
 /* Encryption works on a sector granularity */
+if (!s->crypto) {
+error_setg(errp, "Encryption context is missing");
+return;
+}
 bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
 }
 bs->bl.pwrite_zeroes_alignment = s->subcluster_size;
-- 
2.42.2




[PATCH 3/4] qemu-img: prevent stack overflow in bench by using bottom half

2025-03-27 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

Previously, new I/O requests were launched synchronously inside the
completion callback `bench_cb`, leading to deep recursion and stack
overflow. This patch moves the launching of new requests to a separate
function `bench_bh`, scheduled via `qemu_bh_schedule` to run in the event
loop context, thus unwinding the stack and preventing overflow.

Signed-off-by: Vasiliy Kovalev 
Signed-off-by: Denis Rastyogin 
---
 qemu-img.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/qemu-img.c b/qemu-img.c
index 71c9fe496f..5cbf3d18d7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4426,6 +4426,7 @@ typedef struct BenchData {
 int in_flight;
 bool in_flush;
 uint64_t offset;
+QEMUBH *bh;
 } BenchData;
 
 static void bench_undrained_flush_cb(void *opaque, int ret)
@@ -4479,7 +4480,16 @@ static void bench_cb(void *opaque, int ret)
 }
 }
 }
+if (b->n > b->in_flight && b->in_flight < b->nrreq) {
+qemu_bh_schedule(b->bh);
+}
+}
 
+static void bench_bh(void *opaque)
+{
+BenchData *b = opaque;
+BlockAIOCB *acb;
+
 while (b->n > b->in_flight && b->in_flight < b->nrreq) {
 int64_t offset = b->offset;
 /* blk_aio_* might look for completed I/Os and kick bench_cb
@@ -4737,6 +4747,7 @@ static int img_bench(int argc, char **argv)
 }
 
 gettimeofday(&t1, NULL);
+data.bh = qemu_bh_new(bench_bh, &data);
 bench_cb(&data, 0);
 
 while (data.n > 0) {
@@ -4755,6 +4766,9 @@ out:
 qemu_vfree(data.buf);
 blk_unref(blk);
 
+if (data.bh) {
+qemu_bh_delete(data.bh);
+}
 if (ret) {
 return 1;
 }
-- 
2.42.2




[PATCH 4/4] qemu-img: improve queue depth validation in img_bench

2025-03-27 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

Currently, running `qemu-img bench -d 0` in img_bench is allowed,
which is a pointless operation and causes qemu-img to hang.

Signed-off-by: Denis Rastyogin 
---
 qemu-img.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qemu-img.c b/qemu-img.c
index 5cbf3d18d7..4817bd9b05 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4581,7 +4581,7 @@ static int img_bench(int argc, char **argv)
 {
 unsigned long res;
 
-if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
+if (qemu_strtoul(optarg, NULL, 0, &res) <= 0 || res > INT_MAX) {
 error_report("Invalid queue depth specified");
 return 1;
 }
-- 
2.42.2




[PATCH 2/4] qemu-img: fix offset calculation in bench

2025-03-27 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

The current offset calculation leads to an EIO error
in block/block-backend.c: blk_check_byte_request():

 if (offset > len || len - offset < bytes) {
 return -EIO;
 }

This triggers the error message:
"qemu-img: Failed request: Input/output error".

Example of the issue:
 offset: 260076
 len: 260096
 bytes: 4096

This fix ensures that offset remains within a valid range.

Signed-off-by: Denis Rastyogin 
---
 qemu-img.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qemu-img.c b/qemu-img.c
index 2044c22a4c..71c9fe496f 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4491,7 +4491,7 @@ static void bench_cb(void *opaque, int ret)
 if (b->image_size == 0) {
 b->offset = 0;
 } else {
-b->offset %= b->image_size;
+b->offset %= b->image_size - b->bufsize;
 }
 if (b->write) {
 acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
-- 
2.42.2




[PATCH 0/4] Fix qemu-img bench issues and improve checks

2025-03-27 Thread gerben
From: Denis Rastyogin 

This series fixes several qemu-img crashes found during fuzzing.

The patch "qemu-img: fix division by zero in bench_cb() for zero-sized" 
was already submitted earlier:  
https://lore.kernel.org/qemu-devel/20250318101933.255617-1-ger...@altlinux.org/ 
 

However, it has been included in this series because it 
has not yet been merged into master.  Without it, the series 
would conflict with this commit due to modifications 
in the same parts of the code.  

Denis Rastyogin (4):
  qemu-img: fix division by zero in bench_cb() for zero-sized
  qemu-img: fix offset calculation in bench
  qemu-img: prevent stack overflow in bench by using bottom half
  qemu-img: improve queue depth validation in img_bench

 qemu-img.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

-- 
2.42.2




[PATCH 1/4] qemu-img: fix division by zero in bench_cb() for zero-sized

2025-03-27 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

This commit fixes a division by zero error in the bench_cb() function
that occurs when using the bench command with a zero-sized image.

The issue arises because b->image_size can be zero, leading to a
division by zero in the modulo operation (b->offset %= b->image_size).
This patch adds a check for b->image_size == 0 and resets b->offset
to 0 in such cases, preventing the error.

Signed-off-by: Denis Rastyogin 
---
 qemu-img.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/qemu-img.c b/qemu-img.c
index 89c93c1eb5..2044c22a4c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4488,7 +4488,11 @@ static void bench_cb(void *opaque, int ret)
  */
 b->in_flight++;
 b->offset += b->step;
-b->offset %= b->image_size;
+if (b->image_size == 0) {
+b->offset = 0;
+} else {
+b->offset %= b->image_size;
+}
 if (b->write) {
 acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
 } else {
-- 
2.42.2




[PATCH v2] qemu-img: fix offset calculation in bench

2025-05-06 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

The current offset calculation leads to an EIO error
in block/block-backend.c: blk_check_byte_request():

 if (offset > len || len - offset < bytes) {
 return -EIO;
 }

This triggers the error message:
"qemu-img: Failed request: Input/output error".

Example of the issue:
 offset: 260076
 len: 260096
 bytes: 4096

This fix ensures that offset remains within a valid range.

Signed-off-by: Denis Rastyogin 
---
 qemu-img.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 76ac5d3028..e64acfafb3 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4488,10 +4488,10 @@ static void bench_cb(void *opaque, int ret)
  */
 b->in_flight++;
 b->offset += b->step;
-if (b->image_size == 0) {
+if (b->image_size - b->bufsize <= 0) {
 b->offset = 0;
 } else {
-b->offset %= b->image_size;
+b->offset %= b->image_size - b->bufsize;
 }
 if (b->write) {
 acb = blk_aio_pwritev(b->blk, offset, b->qiov, 0, bench_cb, b);
-- 
2.42.2




[PATCH] qcow2: add check for correctness of refcounts

2025-05-06 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

Refcounts in an image may point beyond the end of the file.
In this case, we cannot resize such images. Otherwise,
we will at least catch it in qcow2_refcount_area() with
assert(s->get_refcount(refblock_data, j) == 0).

This check ensures that refcounts do not point beyond the end of the file.

Signed-off-by: Denis Rastyogin 
---
 block/qcow2.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/block/qcow2.c b/block/qcow2.c
index 7774e7f090..b053a313f2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4452,6 +4452,7 @@ qcow2_co_truncate(BlockDriverState *bs, int64_t offset, 
bool exact,
 int64_t allocation_start, host_offset, guest_offset;
 int64_t clusters_allocated;
 int64_t old_file_size, last_cluster, new_file_size;
+int64_t old_size, last_used_cluster;
 uint64_t nb_new_data_clusters, nb_new_l2_tables;
 bool subclusters_need_allocation = false;
 
@@ -4480,6 +4481,27 @@ qcow2_co_truncate(BlockDriverState *bs, int64_t offset, 
bool exact,
 old_file_size = ROUND_UP(old_file_size, s->cluster_size);
 }
 
+/* Ensure that refcount does not point past the end of the actual file 
size.
+ * If refcount refers to regions beyond the file size, we can't 
properly call
+ * qcow2_refcount_area. */
+old_size = bdrv_co_getlength(bs);
+if (old_size < 0) {
+error_setg_errno(errp, -old_size,
+ "Failed to inquire current length");
+ret = old_size;
+goto fail;
+}
+
+last_used_cluster = qcow2_get_last_cluster(bs, old_size);
+if (last_used_cluster >= old_file_size / s->cluster_size) {
+error_setg(errp,
+"Can't resize: last used cluster (%" PRId64
+") exceeds file size (%" PRIu64 " clusters)",
+last_used_cluster, old_file_size / s->cluster_size);
+ret = -ERANGE;
+goto fail;
+}
+
 nb_new_data_clusters = (ROUND_UP(offset, s->cluster_size) -
 start_of_cluster(s, old_length)) >> s->cluster_bits;
 
-- 
2.42.2




[PATCH] block/qed: fix use-after-free by nullifying timer pointer after free

2025-03-04 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

In the QED block driver, the need_check_timer timer is freed in
bdrv_qed_detach_aio_context, but the pointer to the timer is not
set to NULL. This can lead to a use-after-free scenario
in bdrv_qed_drain_begin().

The need_check_timer pointer is set to NULL after freeing the timer.
Which helps catch this condition when checking in bdrv_qed_drain_begin().

Closes: https://gitlab.com/qemu-project/qemu/-/issues/2852
Signed-off-by: Denis Rastyogin 
---
 block/qed.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/qed.c b/block/qed.c
index 382c9e5335..ac24449ffb 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -353,6 +353,7 @@ static void bdrv_qed_detach_aio_context(BlockDriverState 
*bs)
 
 qed_cancel_need_check_timer(s);
 timer_free(s->need_check_timer);
+s->need_check_timer = NULL;
 }
 
 static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
-- 
2.42.2




[PATCH] block/vmdk: prevent double-free in extent memory management

2025-03-04 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

A double-free issue in the VMDK driver occurs when handling snapshots.
The memory allocated for extent structures is freed twice: first in
vmdk_close (block/vmdk.c) and then in vmdk_add_extent (block/vmdk.c).

The fix ensures the s->extents pointer is set to NULL after freeing,
preventing double-free.

Closes: https://gitlab.com/qemu-project/qemu/-/issues/2853
Signed-off-by: Denis Rastyogin 
---
 block/vmdk.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/vmdk.c b/block/vmdk.c
index 2adec49912..d6baa54602 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -285,6 +285,7 @@ static void vmdk_free_extents(BlockDriverState *bs)
 bdrv_graph_wrunlock();
 
 g_free(s->extents);
+s->extents = NULL;
 }
 
 static void vmdk_free_last_extent(BlockDriverState *bs)
-- 
2.42.2




[PATCH] block/snapshot: fix *errp handling in bdrv_snapshot_goto

2025-03-04 Thread gerben
From: Denis Rastyogin 

This error was discovered by fuzzing qemu-img.

If bdrv_snapshot_goto() returns an error, it is not handled immediately,
allowing *errp to be reassigned when qcow_open() fails, which triggers
assert(*errp == NULL) in util/error.c: void error_setv().

This patch ensures that errors from bdrv_snapshot_goto() are handled
immediately after the call, preventing *errp from being modified twice
and avoiding unnecessary assertion failures.

Closes: https://gitlab.com/qemu-project/qemu/-/issues/2851
Signed-off-by: Denis Rastyogin 
---
 block/snapshot.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/block/snapshot.c b/block/snapshot.c
index 9c44780e96..d1b5a8d33d 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -296,14 +296,20 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
 bdrv_graph_wrunlock();
 
 ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
+if (ret < 0) {
+bdrv_unref(fallback_bs);
+bs->drv = NULL;
+/* A bdrv_snapshot_goto() error takes precedence */
+error_propagate(errp, local_err);
+return ret;
+}
 open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
 qobject_unref(options);
 if (open_ret < 0) {
 bdrv_unref(fallback_bs);
 bs->drv = NULL;
-/* A bdrv_snapshot_goto() error takes precedence */
 error_propagate(errp, local_err);
-return ret < 0 ? ret : open_ret;
+return open_ret;
 }
 
 /*
-- 
2.42.2




[PATCH] linux-user: check for NULL before using interval_tree_iter_first result

2025-07-22 Thread gerben
From: Denis Rastyogin 

interval_tree_iter_first() may return NULL if the interval tree is empty or 
invalid.
Add a check for NULL before dereferencing the pointer to avoid potential crashes
due to null pointer dereference in open_self_maps_2().

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Denis Rastyogin 
---
 linux-user/syscall.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 91360a072c..d5d5912c96 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8172,6 +8172,9 @@ static int open_self_maps_2(void *opaque, vaddr 
guest_start,
 while (1) {
 IntervalTreeNode *n =
 interval_tree_iter_first(d->host_maps, host_start, host_start);
+if (n == NULL) {
+return -1;
+}
 MapInfo *mi = container_of(n, MapInfo, itree);
 uintptr_t this_hlast = MIN(host_last, n->last);
 target_ulong this_gend = h2g(this_hlast) + 1;
-- 
2.42.2




[PATCH] target/ppc: fix potential shift overflow by using 64-bit constant

2025-07-22 Thread gerben
From: Denis Rastyogin 

Change shift operand from 32-bit literal `1` to 64-bit `1ULL` to avoid 
undefined behavior
when shifting bits beyond the width of a 32-bit integer.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Denis Rastyogin 
---
 target/ppc/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 27f90c3cc5..8e69c4cb48 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2998,7 +2998,7 @@ static void gen_fetch_inc_conditional(DisasContext *ctx, 
MemOp memop,
 
 /* RT = (t != t2 ? t : u = 1<<(s*8-1)) */
 tcg_gen_movcond_tl(cond, cpu_gpr[rD(ctx->opcode)], t, t2, t,
-   tcg_constant_tl(1 << (memop_size(memop) * 8 - 1)));
+   tcg_constant_tl(1ULL << (memop_size(memop) * 8 - 1)));
 }
 
 static void gen_ld_atomic(DisasContext *ctx, MemOp memop)
-- 
2.42.2




[PATCH] target/mips: fix TLB huge page check to use 64-bit shift

2025-07-22 Thread gerben
From: Denis Rastyogin 

Use 1ULL << psn to ensure the shift is done in 64-bit arithmetic,
avoiding overflow for large psn values. The 6-bit psn field allows
values up to 63, so 64-bit shift is required for correctness.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Denis Rastyogin 
---
 target/mips/tcg/system/tlb_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/mips/tcg/system/tlb_helper.c 
b/target/mips/tcg/system/tlb_helper.c
index eccaf3624c..b8b8747064 100644
--- a/target/mips/tcg/system/tlb_helper.c
+++ b/target/mips/tcg/system/tlb_helper.c
@@ -652,7 +652,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t 
*vaddr,
 return 0;
 }
 
-if ((entry & (1 << psn)) && hugepg) {
+if ((entry & (1ULL << psn)) && hugepg) {
 *huge_page = true;
 *hgpg_directory_hit = true;
 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew);
-- 
2.42.2




[PATCH] target/hppa: prevent overflow in BTLB entry size calculation

2025-07-22 Thread gerben
From: Denis Rastyogin 

Cast len to long long before multiplying by TARGET_PAGE_SIZE
when calculating btlb->itree.last to ensure 64-bit arithmetic
and avoid potential overflow.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Denis Rastyogin 
---
 target/hppa/mem_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 9bdd0a6f23..0c196b5bfc 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -766,7 +766,7 @@ void HELPER(diag_btlb)(CPUHPPAState *env)
 
 /* Create new BTLB entry */
 btlb->itree.start = virt_page << TARGET_PAGE_BITS;
-btlb->itree.last = btlb->itree.start + len * TARGET_PAGE_SIZE - 1;
+btlb->itree.last = btlb->itree.start + (long long) len * 
TARGET_PAGE_SIZE - 1;
 btlb->pa = phys_page << TARGET_PAGE_BITS;
 set_access_bits_pa11(env, btlb, env->gr[20]);
 btlb->t = 0;
-- 
2.42.2




[PATCH] hw/display: refine upper limit for offset value in assert check

2025-07-22 Thread gerben
From: Denis Rastyogin 

Accessing s->core_registers (size 236) could overflow
if the offset goes beyond the valid range.

Since the memory region matches core_registers size exactly,
guest cannot write out-of-bounds.

Therefore, the debug assert has been refined to ensure the offset
remains within DP_CORE_REG_ARRAY_SIZE, preventing internal errors.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Reported-by: David Meliksetyan 
Signed-off-by: Denis Rastyogin 
---
 hw/display/xlnx_dp.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 7c980ee642..b35ee2f869 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -896,7 +896,11 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, 
uint64_t value,
 xlnx_dp_update_irq(s);
 break;
 default:
-assert(offset <= (0x504C >> 2));
+/*
+ * Check to ensure the offset is within the bounds of
+ * the core_registers[] array.
+ */
+assert(offset < DP_CORE_REG_ARRAY_SIZE);
 s->core_registers[offset] = value;
 break;
 }
-- 
2.42.2