[PATCH v2] hw/display: refine upper limit for offset value in assert check
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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