* [Qemu-devel] [PATCH 0/2] VHDX cleanup
@ 2017-08-07 3:08 Jeff Cody
2017-08-07 3:08 ` [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength() Jeff Cody
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Jeff Cody @ 2017-08-07 3:08 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, armbru
Two VHDX items cleaned up:
1. Check for error when calling bdrv_getlength() [Markus]
2. Check for overflow in offset prior to calling bdrv_truncate().
Jeff Cody (2):
block/vhdx: check error return of bdrv_getlength()
block/vhdx: check for offset overflow to bdrv_truncate()
block/vhdx-log.c | 24 ++++++++++++++++++++----
block/vhdx.c | 12 +++++++++++-
2 files changed, 31 insertions(+), 5 deletions(-)
--
2.9.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength()
2017-08-07 3:08 [Qemu-devel] [PATCH 0/2] VHDX cleanup Jeff Cody
@ 2017-08-07 3:08 ` Jeff Cody
2017-08-07 10:46 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2017-08-07 11:25 ` [Qemu-devel] " Eric Blake
2017-08-07 3:08 ` [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate() Jeff Cody
2017-08-07 10:48 ` [Qemu-devel] [Qemu-block] [PATCH 0/2] VHDX cleanup Kevin Wolf
2 siblings, 2 replies; 10+ messages in thread
From: Jeff Cody @ 2017-08-07 3:08 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, armbru
Calls to bdrv_getlength() were not checking for error. In vhdx.c, this
can lead to truncating an image file, so it is a definite bug. In
vhdx-log.c, the path for improper behavior is less clear, but it is best
to check in any case.
Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
---
block/vhdx-log.c | 20 ++++++++++++++++----
block/vhdx.c | 9 ++++++++-
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
index 01278f3..fd4e7af 100644
--- a/block/vhdx-log.c
+++ b/block/vhdx-log.c
@@ -491,6 +491,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
uint32_t cnt, sectors_read;
uint64_t new_file_size;
void *data = NULL;
+ int64_t file_length;
VHDXLogDescEntries *desc_entries = NULL;
VHDXLogEntryHeader hdr_tmp = { 0 };
@@ -510,10 +511,15 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
if (ret < 0) {
goto exit;
}
+ file_length = bdrv_getlength(bs->file->bs);
+ if (file_length < 0) {
+ ret = file_length;
+ goto exit;
+ }
/* if the log shows a FlushedFileOffset larger than our current file
* size, then that means the file has been truncated / corrupted, and
* we must refused to open it / use it */
- if (hdr_tmp.flushed_file_offset > bdrv_getlength(bs->file->bs)) {
+ if (hdr_tmp.flushed_file_offset > file_length) {
ret = -EINVAL;
goto exit;
}
@@ -543,7 +549,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
goto exit;
}
}
- if (bdrv_getlength(bs->file->bs) < desc_entries->hdr.last_file_offset) {
+ if (file_length < desc_entries->hdr.last_file_offset) {
new_file_size = desc_entries->hdr.last_file_offset;
if (new_file_size % (1024*1024)) {
/* round up to nearest 1MB boundary */
@@ -851,6 +857,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
uint32_t partial_sectors = 0;
uint32_t bytes_written = 0;
uint64_t file_offset;
+ int64_t file_length;
VHDXHeader *header;
VHDXLogEntryHeader new_hdr;
VHDXLogDescriptor *new_desc = NULL;
@@ -913,10 +920,15 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
.sequence_number = s->log.sequence,
.descriptor_count = sectors,
.reserved = 0,
- .flushed_file_offset = bdrv_getlength(bs->file->bs),
- .last_file_offset = bdrv_getlength(bs->file->bs),
};
+ file_length = bdrv_getlength(bs->file->bs);
+ if (file_length < 0) {
+ ret = file_length;
+ goto exit;
+ }
+ new_hdr.flushed_file_offset = file_length;
+ new_hdr.last_file_offset = file_length;
new_hdr.log_guid = header->log_guid;
desc_sectors = vhdx_compute_desc_sectors(new_hdr.descriptor_count);
diff --git a/block/vhdx.c b/block/vhdx.c
index a9cecd2..6a14999 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1166,7 +1166,14 @@ exit:
static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
uint64_t *new_offset)
{
- *new_offset = bdrv_getlength(bs->file->bs);
+ int64_t current_len;
+ current_len = bdrv_getlength(bs->file->bs);
+
+ if (current_len < 0) {
+ return current_len;
+ }
+
+ *new_offset = current_len;
/* per the spec, the address for a block is in units of 1MB */
*new_offset = ROUND_UP(*new_offset, 1024 * 1024);
--
2.9.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate()
2017-08-07 3:08 [Qemu-devel] [PATCH 0/2] VHDX cleanup Jeff Cody
2017-08-07 3:08 ` [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength() Jeff Cody
@ 2017-08-07 3:08 ` Jeff Cody
2017-08-07 10:48 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2017-08-07 11:24 ` [Qemu-devel] " Eric Blake
2017-08-07 10:48 ` [Qemu-devel] [Qemu-block] [PATCH 0/2] VHDX cleanup Kevin Wolf
2 siblings, 2 replies; 10+ messages in thread
From: Jeff Cody @ 2017-08-07 3:08 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, armbru
VHDX uses uint64_t types for most offsets, following the VHDX spec.
However, bdrv_truncate() takes an int64_t value for the truncating
offset. Check for overflow before calling bdrv_truncate().
N.B.: For a compliant image this is not an issue, as the maximum VHDX
image size is defined per the spec to be 64TB.
Signed-off-by: Jeff Cody <jcody@redhat.com>
---
block/vhdx-log.c | 4 ++++
block/vhdx.c | 3 +++
2 files changed, 7 insertions(+)
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
index fd4e7af..3b74e5d 100644
--- a/block/vhdx-log.c
+++ b/block/vhdx-log.c
@@ -554,6 +554,10 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
if (new_file_size % (1024*1024)) {
/* round up to nearest 1MB boundary */
new_file_size = ((new_file_size >> 20) + 1) << 20;
+ if (new_file_size > INT64_MAX) {
+ ret = -EINVAL;
+ goto exit;
+ }
bdrv_truncate(bs->file, new_file_size, PREALLOC_MODE_OFF, NULL);
}
}
diff --git a/block/vhdx.c b/block/vhdx.c
index 6a14999..c45af73 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1177,6 +1177,9 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
/* per the spec, the address for a block is in units of 1MB */
*new_offset = ROUND_UP(*new_offset, 1024 * 1024);
+ if (*new_offset > INT64_MAX) {
+ return -EINVAL;
+ }
return bdrv_truncate(bs->file, *new_offset + s->block_size,
PREALLOC_MODE_OFF, NULL);
--
2.9.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength()
2017-08-07 3:08 ` [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength() Jeff Cody
@ 2017-08-07 10:46 ` Kevin Wolf
2017-08-07 12:16 ` Jeff Cody
2017-08-07 11:25 ` [Qemu-devel] " Eric Blake
1 sibling, 1 reply; 10+ messages in thread
From: Kevin Wolf @ 2017-08-07 10:46 UTC (permalink / raw)
To: Jeff Cody; +Cc: qemu-devel, armbru, qemu-block
Am 07.08.2017 um 05:08 hat Jeff Cody geschrieben:
> Calls to bdrv_getlength() were not checking for error. In vhdx.c, this
> can lead to truncating an image file, so it is a definite bug. In
> vhdx-log.c, the path for improper behavior is less clear, but it is best
> to check in any case.
>
> Reported-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Jeff Cody <jcody@redhat.com>
> ---
> block/vhdx-log.c | 20 ++++++++++++++++----
> block/vhdx.c | 9 ++++++++-
> 2 files changed, 24 insertions(+), 5 deletions(-)
>
> diff --git a/block/vhdx-log.c b/block/vhdx-log.c
> index 01278f3..fd4e7af 100644
> --- a/block/vhdx-log.c
> +++ b/block/vhdx-log.c
> @@ -491,6 +491,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> uint32_t cnt, sectors_read;
> uint64_t new_file_size;
> void *data = NULL;
> + int64_t file_length;
> VHDXLogDescEntries *desc_entries = NULL;
> VHDXLogEntryHeader hdr_tmp = { 0 };
>
> @@ -510,10 +511,15 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> if (ret < 0) {
> goto exit;
> }
> + file_length = bdrv_getlength(bs->file->bs);
> + if (file_length < 0) {
> + ret = file_length;
> + goto exit;
> + }
> /* if the log shows a FlushedFileOffset larger than our current file
> * size, then that means the file has been truncated / corrupted, and
> * we must refused to open it / use it */
> - if (hdr_tmp.flushed_file_offset > bdrv_getlength(bs->file->bs)) {
> + if (hdr_tmp.flushed_file_offset > file_length) {
> ret = -EINVAL;
> goto exit;
> }
> @@ -543,7 +549,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> goto exit;
> }
> }
> - if (bdrv_getlength(bs->file->bs) < desc_entries->hdr.last_file_offset) {
> + if (file_length < desc_entries->hdr.last_file_offset) {
> new_file_size = desc_entries->hdr.last_file_offset;
> if (new_file_size % (1024*1024)) {
> /* round up to nearest 1MB boundary */
The vhdx_log_flush() part looks good, but it made me notice a
bdrv_flush() in the same function where the return value isn't checked.
I'm almost sure that this is a bug.
> @@ -851,6 +857,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
> uint32_t partial_sectors = 0;
> uint32_t bytes_written = 0;
> uint64_t file_offset;
> + int64_t file_length;
> VHDXHeader *header;
> VHDXLogEntryHeader new_hdr;
> VHDXLogDescriptor *new_desc = NULL;
> @@ -913,10 +920,15 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
> .sequence_number = s->log.sequence,
> .descriptor_count = sectors,
> .reserved = 0,
> - .flushed_file_offset = bdrv_getlength(bs->file->bs),
> - .last_file_offset = bdrv_getlength(bs->file->bs),
> };
>
> + file_length = bdrv_getlength(bs->file->bs);
> + if (file_length < 0) {
> + ret = file_length;
> + goto exit;
> + }
> + new_hdr.flushed_file_offset = file_length;
> + new_hdr.last_file_offset = file_length;
> new_hdr.log_guid = header->log_guid;
If you move the bdrv_getlength() above the initialisation of new_hdr,
you could keep these fields in the designated initialiser, which should
be better for readability.
I also don't know why .log_guid isn't part if it, could be moved, too.
> desc_sectors = vhdx_compute_desc_sectors(new_hdr.descriptor_count);
> diff --git a/block/vhdx.c b/block/vhdx.c
> index a9cecd2..6a14999 100644
> --- a/block/vhdx.c
> +++ b/block/vhdx.c
> @@ -1166,7 +1166,14 @@ exit:
> static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
> uint64_t *new_offset)
> {
> - *new_offset = bdrv_getlength(bs->file->bs);
> + int64_t current_len;
> + current_len = bdrv_getlength(bs->file->bs);
> +
> + if (current_len < 0) {
> + return current_len;
> + }
Don't you want the empty line to be between declaration and code rather
than assignment and check?
> + *new_offset = current_len;
>
> /* per the spec, the address for a block is in units of 1MB */
> *new_offset = ROUND_UP(*new_offset, 1024 * 1024);
So the code looks correct, but we could make it a little nicer in a v2.
Kevin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate()
2017-08-07 3:08 ` [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate() Jeff Cody
@ 2017-08-07 10:48 ` Kevin Wolf
2017-08-07 11:24 ` [Qemu-devel] " Eric Blake
1 sibling, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2017-08-07 10:48 UTC (permalink / raw)
To: Jeff Cody; +Cc: qemu-devel, armbru, qemu-block
Am 07.08.2017 um 05:08 hat Jeff Cody geschrieben:
> VHDX uses uint64_t types for most offsets, following the VHDX spec.
> However, bdrv_truncate() takes an int64_t value for the truncating
> offset. Check for overflow before calling bdrv_truncate().
>
> N.B.: For a compliant image this is not an issue, as the maximum VHDX
> image size is defined per the spec to be 64TB.
>
> Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH 0/2] VHDX cleanup
2017-08-07 3:08 [Qemu-devel] [PATCH 0/2] VHDX cleanup Jeff Cody
2017-08-07 3:08 ` [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength() Jeff Cody
2017-08-07 3:08 ` [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate() Jeff Cody
@ 2017-08-07 10:48 ` Kevin Wolf
2 siblings, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2017-08-07 10:48 UTC (permalink / raw)
To: Jeff Cody; +Cc: qemu-devel, armbru, qemu-block
Am 07.08.2017 um 05:08 hat Jeff Cody geschrieben:
> Two VHDX items cleaned up:
>
> 1. Check for error when calling bdrv_getlength() [Markus]
>
> 2. Check for overflow in offset prior to calling bdrv_truncate().
This doesn't look like cleanups to me, but like proper fixes. I think it
would still qualify for 2.10.
Kevin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate()
2017-08-07 3:08 ` [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate() Jeff Cody
2017-08-07 10:48 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
@ 2017-08-07 11:24 ` Eric Blake
2017-08-07 12:13 ` Jeff Cody
1 sibling, 1 reply; 10+ messages in thread
From: Eric Blake @ 2017-08-07 11:24 UTC (permalink / raw)
To: Jeff Cody, qemu-devel; +Cc: armbru, qemu-block
[-- Attachment #1: Type: text/plain, Size: 1432 bytes --]
On 08/06/2017 10:08 PM, Jeff Cody wrote:
> VHDX uses uint64_t types for most offsets, following the VHDX spec.
> However, bdrv_truncate() takes an int64_t value for the truncating
> offset. Check for overflow before calling bdrv_truncate().
>
> N.B.: For a compliant image this is not an issue, as the maximum VHDX
> image size is defined per the spec to be 64TB.
>
> Signed-off-by: Jeff Cody <jcody@redhat.com>
> ---
> block/vhdx-log.c | 4 ++++
> block/vhdx.c | 3 +++
> 2 files changed, 7 insertions(+)
>
> diff --git a/block/vhdx-log.c b/block/vhdx-log.c
> index fd4e7af..3b74e5d 100644
> --- a/block/vhdx-log.c
> +++ b/block/vhdx-log.c
> @@ -554,6 +554,10 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> if (new_file_size % (1024*1024)) {
> /* round up to nearest 1MB boundary */
> new_file_size = ((new_file_size >> 20) + 1) << 20;
Since you're touching here, can you fix this to use QEMU_ALIGN_UP instead?
> + if (new_file_size > INT64_MAX) {
> + ret = -EINVAL;
> + goto exit;
> + }
> bdrv_truncate(bs->file, new_file_size, PREALLOC_MODE_OFF, NULL);
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength()
2017-08-07 3:08 ` [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength() Jeff Cody
2017-08-07 10:46 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
@ 2017-08-07 11:25 ` Eric Blake
1 sibling, 0 replies; 10+ messages in thread
From: Eric Blake @ 2017-08-07 11:25 UTC (permalink / raw)
To: Jeff Cody, qemu-devel; +Cc: armbru, qemu-block
[-- Attachment #1: Type: text/plain, Size: 716 bytes --]
On 08/06/2017 10:08 PM, Jeff Cody wrote:
> Calls to bdrv_getlength() were not checking for error. In vhdx.c, this
> can lead to truncating an image file, so it is a definite bug. In
> vhdx-log.c, the path for improper behavior is less clear, but it is best
> to check in any case.
>
> Reported-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Jeff Cody <jcody@redhat.com>
> ---
> block/vhdx-log.c | 20 ++++++++++++++++----
> block/vhdx.c | 9 ++++++++-
> 2 files changed, 24 insertions(+), 5 deletions(-)
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate()
2017-08-07 11:24 ` [Qemu-devel] " Eric Blake
@ 2017-08-07 12:13 ` Jeff Cody
0 siblings, 0 replies; 10+ messages in thread
From: Jeff Cody @ 2017-08-07 12:13 UTC (permalink / raw)
To: Eric Blake; +Cc: qemu-devel, armbru, qemu-block
On Mon, Aug 07, 2017 at 06:24:30AM -0500, Eric Blake wrote:
> On 08/06/2017 10:08 PM, Jeff Cody wrote:
> > VHDX uses uint64_t types for most offsets, following the VHDX spec.
> > However, bdrv_truncate() takes an int64_t value for the truncating
> > offset. Check for overflow before calling bdrv_truncate().
> >
> > N.B.: For a compliant image this is not an issue, as the maximum VHDX
> > image size is defined per the spec to be 64TB.
> >
> > Signed-off-by: Jeff Cody <jcody@redhat.com>
> > ---
> > block/vhdx-log.c | 4 ++++
> > block/vhdx.c | 3 +++
> > 2 files changed, 7 insertions(+)
> >
> > diff --git a/block/vhdx-log.c b/block/vhdx-log.c
> > index fd4e7af..3b74e5d 100644
> > --- a/block/vhdx-log.c
> > +++ b/block/vhdx-log.c
> > @@ -554,6 +554,10 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> > if (new_file_size % (1024*1024)) {
> > /* round up to nearest 1MB boundary */
> > new_file_size = ((new_file_size >> 20) + 1) << 20;
>
> Since you're touching here, can you fix this to use QEMU_ALIGN_UP instead?
>
Good idea, yes.
> > + if (new_file_size > INT64_MAX) {
> > + ret = -EINVAL;
> > + goto exit;
> > + }
> > bdrv_truncate(bs->file, new_file_size, PREALLOC_MODE_OFF, NULL);
>
> Reviewed-by: Eric Blake <eblake@redhat.com>
>
> --
> Eric Blake, Principal Software Engineer
> Red Hat, Inc. +1-919-301-3266
> Virtualization: qemu.org | libvirt.org
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [Qemu-block] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength()
2017-08-07 10:46 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
@ 2017-08-07 12:16 ` Jeff Cody
0 siblings, 0 replies; 10+ messages in thread
From: Jeff Cody @ 2017-08-07 12:16 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-devel, armbru, qemu-block
On Mon, Aug 07, 2017 at 12:46:30PM +0200, Kevin Wolf wrote:
> Am 07.08.2017 um 05:08 hat Jeff Cody geschrieben:
> > Calls to bdrv_getlength() were not checking for error. In vhdx.c, this
> > can lead to truncating an image file, so it is a definite bug. In
> > vhdx-log.c, the path for improper behavior is less clear, but it is best
> > to check in any case.
> >
> > Reported-by: Markus Armbruster <armbru@redhat.com>
> > Signed-off-by: Jeff Cody <jcody@redhat.com>
> > ---
> > block/vhdx-log.c | 20 ++++++++++++++++----
> > block/vhdx.c | 9 ++++++++-
> > 2 files changed, 24 insertions(+), 5 deletions(-)
> >
> > diff --git a/block/vhdx-log.c b/block/vhdx-log.c
> > index 01278f3..fd4e7af 100644
> > --- a/block/vhdx-log.c
> > +++ b/block/vhdx-log.c
> > @@ -491,6 +491,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> > uint32_t cnt, sectors_read;
> > uint64_t new_file_size;
> > void *data = NULL;
> > + int64_t file_length;
> > VHDXLogDescEntries *desc_entries = NULL;
> > VHDXLogEntryHeader hdr_tmp = { 0 };
> >
> > @@ -510,10 +511,15 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> > if (ret < 0) {
> > goto exit;
> > }
> > + file_length = bdrv_getlength(bs->file->bs);
> > + if (file_length < 0) {
> > + ret = file_length;
> > + goto exit;
> > + }
> > /* if the log shows a FlushedFileOffset larger than our current file
> > * size, then that means the file has been truncated / corrupted, and
> > * we must refused to open it / use it */
> > - if (hdr_tmp.flushed_file_offset > bdrv_getlength(bs->file->bs)) {
> > + if (hdr_tmp.flushed_file_offset > file_length) {
> > ret = -EINVAL;
> > goto exit;
> > }
> > @@ -543,7 +549,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
> > goto exit;
> > }
> > }
> > - if (bdrv_getlength(bs->file->bs) < desc_entries->hdr.last_file_offset) {
> > + if (file_length < desc_entries->hdr.last_file_offset) {
> > new_file_size = desc_entries->hdr.last_file_offset;
> > if (new_file_size % (1024*1024)) {
> > /* round up to nearest 1MB boundary */
>
> The vhdx_log_flush() part looks good, but it made me notice a
> bdrv_flush() in the same function where the return value isn't checked.
> I'm almost sure that this is a bug.
>
I'll add 2 more simple patches to the series: one for bdrv_flush(), and one
for the unchecked bdrv_truncate() as well.
> > @@ -851,6 +857,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
> > uint32_t partial_sectors = 0;
> > uint32_t bytes_written = 0;
> > uint64_t file_offset;
> > + int64_t file_length;
> > VHDXHeader *header;
> > VHDXLogEntryHeader new_hdr;
> > VHDXLogDescriptor *new_desc = NULL;
> > @@ -913,10 +920,15 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
> > .sequence_number = s->log.sequence,
> > .descriptor_count = sectors,
> > .reserved = 0,
> > - .flushed_file_offset = bdrv_getlength(bs->file->bs),
> > - .last_file_offset = bdrv_getlength(bs->file->bs),
> > };
> >
> > + file_length = bdrv_getlength(bs->file->bs);
> > + if (file_length < 0) {
> > + ret = file_length;
> > + goto exit;
> > + }
> > + new_hdr.flushed_file_offset = file_length;
> > + new_hdr.last_file_offset = file_length;
> > new_hdr.log_guid = header->log_guid;
>
> If you move the bdrv_getlength() above the initialisation of new_hdr,
> you could keep these fields in the designated initialiser, which should
> be better for readability.
>
> I also don't know why .log_guid isn't part if it, could be moved, too.
>
> > desc_sectors = vhdx_compute_desc_sectors(new_hdr.descriptor_count);
> > diff --git a/block/vhdx.c b/block/vhdx.c
> > index a9cecd2..6a14999 100644
> > --- a/block/vhdx.c
> > +++ b/block/vhdx.c
> > @@ -1166,7 +1166,14 @@ exit:
> > static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
> > uint64_t *new_offset)
> > {
> > - *new_offset = bdrv_getlength(bs->file->bs);
> > + int64_t current_len;
> > + current_len = bdrv_getlength(bs->file->bs);
> > +
> > + if (current_len < 0) {
> > + return current_len;
> > + }
>
> Don't you want the empty line to be between declaration and code rather
> than assignment and check?
>
> > + *new_offset = current_len;
> >
> > /* per the spec, the address for a block is in units of 1MB */
> > *new_offset = ROUND_UP(*new_offset, 1024 * 1024);
>
> So the code looks correct, but we could make it a little nicer in a v2.
>
Yep, thanks. I'll address all those cleanups you mentioned in v2.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2017-08-07 12:17 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-07 3:08 [Qemu-devel] [PATCH 0/2] VHDX cleanup Jeff Cody
2017-08-07 3:08 ` [Qemu-devel] [PATCH 1/2] block/vhdx: check error return of bdrv_getlength() Jeff Cody
2017-08-07 10:46 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2017-08-07 12:16 ` Jeff Cody
2017-08-07 11:25 ` [Qemu-devel] " Eric Blake
2017-08-07 3:08 ` [Qemu-devel] [PATCH 2/2] block/vhdx: check for offset overflow to bdrv_truncate() Jeff Cody
2017-08-07 10:48 ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2017-08-07 11:24 ` [Qemu-devel] " Eric Blake
2017-08-07 12:13 ` Jeff Cody
2017-08-07 10:48 ` [Qemu-devel] [Qemu-block] [PATCH 0/2] VHDX cleanup Kevin Wolf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).