qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH V2] block/vhdx: add check for truncated image fi


From: Kevin Wolf
Subject: Re: [Qemu-devel] [PATCH V2] block/vhdx: add check for truncated image files
Date: Tue, 3 Sep 2019 15:27:09 +0200
User-agent: Mutt/1.12.0 (2019-05-25)

Am 03.09.2019 um 15:10 hat Peter Lieven geschrieben:
> Am 03.09.19 um 15:02 schrieb Kevin Wolf:
> > Am 02.09.2019 um 17:24 hat Peter Lieven geschrieben:
> > > qemu is currently not able to detect truncated vhdx image files.
> > > Add a basic check if all allocated blocks are reachable at open and
> > > report all errors during bdrv_co_check.
> > > 
> > > Signed-off-by: Peter Lieven <address@hidden>
> > > ---
> > > V2: - add error reporting [Kevin]
> > >      - use bdrv_getlength instead of bdrv_get_allocated_file_size [Kevin]
> > >      - factor out BAT entry check and add error reporting for region
> > >        overlaps
> > >      - already check on vhdx_open
> > > 
> > >   block/vhdx.c | 85 +++++++++++++++++++++++++++++++++++++++++-----------
> > >   1 file changed, 68 insertions(+), 17 deletions(-)
> > > 
> > > diff --git a/block/vhdx.c b/block/vhdx.c
> > > index 6a09d0a55c..6afba5e8c2 100644
> > > --- a/block/vhdx.c
> > > +++ b/block/vhdx.c
> > > @@ -24,6 +24,7 @@
> > >   #include "qemu/option.h"
> > >   #include "qemu/crc32c.h"
> > >   #include "qemu/bswap.h"
> > > +#include "qemu/error-report.h"
> > >   #include "vhdx.h"
> > >   #include "migration/blocker.h"
> > >   #include "qemu/uuid.h"
> > > @@ -235,6 +236,9 @@ static int vhdx_region_check(BDRVVHDXState *s, 
> > > uint64_t start, uint64_t length)
> > >       end = start + length;
> > >       QLIST_FOREACH(r, &s->regions, entries) {
> > >           if (!((start >= r->end) || (end <= r->start))) {
> > > +            error_report("VHDX region %" PRIu64 "-%" PRIu64 " overlaps 
> > > with "
> > > +                         "region %" PRIu64 "-%." PRIu64, start, end, 
> > > r->start,
> > > +                         r->end);
> > >               ret = -EINVAL;
> > >               goto exit;
> > >           }
> > > @@ -877,6 +881,60 @@ static void vhdx_calc_bat_entries(BDRVVHDXState *s)
> > >   }
> > > +static int vhdx_check_bat_entries(BlockDriverState *bs, int *errcnt)
> > > +{
> > > +    BDRVVHDXState *s = bs->opaque;
> > > +    int64_t image_file_size = bdrv_getlength(bs->file->bs);
> > > +    uint64_t payblocks = s->chunk_ratio;
> > > +    int i, ret = 0;
> > bdrv_getlength() can fail. It's probably better to error out immediately
> > instead of reporting that every BAT entry is > -1.
> > 
> > > +    for (i = 0; i < s->bat_entries; i++) {
> > s->bat_entries is uint32_t, so i should probably be the same.
> > 
> > > +        if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
> > > +            PAYLOAD_BLOCK_FULLY_PRESENT) {
> > > +            /*
> > > +             * Check if fully allocated BAT entries do not reside after
> > > +             * end of the image file.
> > > +             */
> > > +            if ((s->bat[i] & VHDX_BAT_FILE_OFF_MASK) + s->block_size >
> > > +                image_file_size) {
> > Didn't we want to introduce an overflow check before making this check?
> > Something like if (bat_offset > UINT64_MAX - s->block_size)?
> 
> Sorry, i missed that.
> 
> The bat entries are UINT64_T so this check will always be false for the
> default block size of 1MB. In fact we should check for
> 
> bat_offset > INT64_MAX - s->block_size
> 
> right?

Hm, VHDX_BAT_FILE_OFF_MASK is 0xFFFFFFFFFFF00000ULL, so 2^64 - 1 MB.
With a block size of 1 MB, this check would trigger because the offset
would be one byte higher than allowed (because offset + block_size
would be 0). For larger block sizes, it's more obvious that we can run
into this case.

As for INT64_MAX, I'm not sure if it's strictly necessary because the
code seems to use unsigned variables everywhere. But it feels safer and
shouldn't make any difference in practice, so I agree with using it.

Kevin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]