The total_sectors is computed as n_blocks * sectors_per_block where
both operands are uint32_t. The multiplication is performed in 32-bit
arithmetic and can overflow when the product exceeds UINT32_MAX,
producing a value much smaller than the true image size. The result
is assigned to int64_t total_sectors but the 32-bit multiplication
has already wrapped around, and the zero-extension to 64-bit does
not recover the correct value.
This causes the block layer to reject valid I/O requests (DoS) when
the reported total_sectors is smaller than the actual image.
Use 64-bit arithmetic by casting one operand to uint64_t so the
multiplication is performed in 64-bit precision.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3972
Signed-off-by: Ma Like <malike@kylinos.cn>
---
block/cloop.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/block/cloop.c b/block/cloop.c
index 443af1444e..a16f08e6ef 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -202,7 +202,8 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
s->current_block = s->n_blocks;
s->sectors_per_block = s->block_size/512;
- bs->total_sectors = s->n_blocks * s->sectors_per_block;
+ /* Cast to uint64_t to prevent uint32_t overflow */
+ bs->total_sectors = (uint64_t)s->n_blocks * s->sectors_per_block;
qemu_co_mutex_init(&s->lock);
return 0;
--
2.25.1