diff mbox series

[1/6] parallels: Incorrect data end calculation in parallels_open()

Message ID 20220902085300.508078-2-alexander.ivanov@virtuozzo.com (mailing list archive)
State New, archived
Headers show
Series parallels: Add duplication check, repair at open, fix bugs | expand

Commit Message

Alexander Ivanov Sept. 2, 2022, 8:52 a.m. UTC
The BDRVParallelsState structure contains data_end field that
is measured in sectors.
In parallels_open() initially this field is set by data_off field from
parallels image header.

According to the parallels format documentation,
data_off field contains an offset, in sectors, from the start of the file
to the start of the data area.
For "WithoutFreeSpace" images: if data_off is zero,
the offset is calculated as the end of the BAT table
plus some padding to ensure sector size alignment.

The parallels_open() function has code for handling zero value
in data_off, but in the result data_end contains the offset in bytes.

Replace the alignment to sector size by division by sector size
and fix the comparision with s->header_size.

Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
---
 block/parallels.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Denis V. Lunev Sept. 7, 2022, 3:23 p.m. UTC | #1
On 9/2/22 10:52, Alexander Ivanov wrote:
> The BDRVParallelsState structure contains data_end field that
> is measured in sectors.
> In parallels_open() initially this field is set by data_off field from
> parallels image header.
>
> According to the parallels format documentation,
> data_off field contains an offset, in sectors, from the start of the file
> to the start of the data area.
> For "WithoutFreeSpace" images: if data_off is zero,
> the offset is calculated as the end of the BAT table
> plus some padding to ensure sector size alignment.
>
> The parallels_open() function has code for handling zero value
> in data_off, but in the result data_end contains the offset in bytes.
>
> Replace the alignment to sector size by division by sector size
> and fix the comparision with s->header_size.
>
> Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
> ---
>   block/parallels.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/block/parallels.c b/block/parallels.c
> index e6e8b9e369..7b4e997ebd 100644
> --- a/block/parallels.c
> +++ b/block/parallels.c
> @@ -863,9 +863,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
>       }
>       s->data_end = le32_to_cpu(ph.data_off);
>       if (s->data_end == 0) {
> -        s->data_end = ROUND_UP(bat_entry_off(s->bat_size), BDRV_SECTOR_SIZE);
> +        s->data_end = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
>       }
> -    if (s->data_end < s->header_size) {
> +    if (s->data_end < (s->header_size >> BDRV_SECTOR_BITS)) {
>           /* there is not enough unused space to fit to block align between BAT
>              and actual data. We can't avoid read-modify-write... */
>           s->header_size = size;
Reviewed-by: Denis V. Lunev <den@openvz.org>

Sidenote: if the image is truncated for more than BAT size and there is 
no data inside
the image, we would get memory corruption during BAT access. That should 
be addressed
separately.
diff mbox series

Patch

diff --git a/block/parallels.c b/block/parallels.c
index e6e8b9e369..7b4e997ebd 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -863,9 +863,9 @@  static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
     }
     s->data_end = le32_to_cpu(ph.data_off);
     if (s->data_end == 0) {
-        s->data_end = ROUND_UP(bat_entry_off(s->bat_size), BDRV_SECTOR_SIZE);
+        s->data_end = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
     }
-    if (s->data_end < s->header_size) {
+    if (s->data_end < (s->header_size >> BDRV_SECTOR_BITS)) {
         /* there is not enough unused space to fit to block align between BAT
            and actual data. We can't avoid read-modify-write... */
         s->header_size = size;