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

gerben@altlinux.org posted 4 patches 10 months, 2 weeks ago
[PATCH 2/4] qemu-img: fix offset calculation in bench
Posted by gerben@altlinux.org 10 months, 2 weeks ago
From: Denis Rastyogin <gerben@altlinux.org>

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 <gerben@altlinux.org>
---
 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
Re: [PATCH 2/4] qemu-img: fix offset calculation in bench
Posted by Kevin Wolf 9 months, 2 weeks ago
Am 27.03.2025 um 17:24 hat gerben@altlinux.org geschrieben:
> From: Denis Rastyogin <gerben@altlinux.org>
> 
> 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 <gerben@altlinux.org>
> ---
>  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;

The approach makes sense in principle, but you just introduced a new
division by zero here if image_size == bufsize (in this case we want to
use 0 as the new offset).

We probably also don't want to allow this to become negative.

Kevin