134 lines
4.8 KiB
Diff
134 lines
4.8 KiB
Diff
From: Kevin Wolf <kwolf@redhat.com>
|
|
Date: Wed, 26 Mar 2014 13:05:31 +0100
|
|
Subject: [PATCH] bochs: Unify header structs and make them QEMU_PACKED
|
|
|
|
This is an on-disk structure, so offsets must be accurate.
|
|
|
|
Before this patch, sizeof(bochs) != sizeof(header_v1), which makes the
|
|
memcpy() between both invalid. We're lucky enough that the destination
|
|
buffer happened to be the larger one, and the memcpy size to be taken
|
|
from the smaller one, so we didn't get a buffer overflow in practice.
|
|
|
|
This patch unifies the both structures, eliminating the need to do a
|
|
memcpy in the first place. The common fields are extracted to the top
|
|
level of the struct and the actually differing part gets a union of the
|
|
two versions.
|
|
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
(cherry picked from commit 3dd8a6763bcc50dfc3de8da9279b741c0dea9fb1)
|
|
---
|
|
block/bochs.c | 67 ++++++++++++++++++++++-------------------------------------
|
|
1 file changed, 25 insertions(+), 42 deletions(-)
|
|
|
|
diff --git a/block/bochs.c b/block/bochs.c
|
|
index d7078c0..d550ce1 100644
|
|
--- a/block/bochs.c
|
|
+++ b/block/bochs.c
|
|
@@ -39,45 +39,30 @@
|
|
// not allocated: 0xffffffff
|
|
|
|
// always little-endian
|
|
-struct bochs_header_v1 {
|
|
- char magic[32]; // "Bochs Virtual HD Image"
|
|
- char type[16]; // "Redolog"
|
|
- char subtype[16]; // "Undoable" / "Volatile" / "Growing"
|
|
- uint32_t version;
|
|
- uint32_t header; // size of header
|
|
-
|
|
- union {
|
|
- struct {
|
|
- uint32_t catalog; // num of entries
|
|
- uint32_t bitmap; // bitmap size
|
|
- uint32_t extent; // extent size
|
|
- uint64_t disk; // disk size
|
|
- char padding[HEADER_SIZE - 64 - 8 - 20];
|
|
- } redolog;
|
|
- char padding[HEADER_SIZE - 64 - 8];
|
|
- } extra;
|
|
-};
|
|
-
|
|
-// always little-endian
|
|
struct bochs_header {
|
|
- char magic[32]; // "Bochs Virtual HD Image"
|
|
- char type[16]; // "Redolog"
|
|
- char subtype[16]; // "Undoable" / "Volatile" / "Growing"
|
|
+ char magic[32]; /* "Bochs Virtual HD Image" */
|
|
+ char type[16]; /* "Redolog" */
|
|
+ char subtype[16]; /* "Undoable" / "Volatile" / "Growing" */
|
|
uint32_t version;
|
|
- uint32_t header; // size of header
|
|
+ uint32_t header; /* size of header */
|
|
+
|
|
+ uint32_t catalog; /* num of entries */
|
|
+ uint32_t bitmap; /* bitmap size */
|
|
+ uint32_t extent; /* extent size */
|
|
|
|
union {
|
|
- struct {
|
|
- uint32_t catalog; // num of entries
|
|
- uint32_t bitmap; // bitmap size
|
|
- uint32_t extent; // extent size
|
|
- uint32_t reserved; // for ???
|
|
- uint64_t disk; // disk size
|
|
- char padding[HEADER_SIZE - 64 - 8 - 24];
|
|
- } redolog;
|
|
- char padding[HEADER_SIZE - 64 - 8];
|
|
+ struct {
|
|
+ uint32_t reserved; /* for ??? */
|
|
+ uint64_t disk; /* disk size */
|
|
+ char padding[HEADER_SIZE - 64 - 20 - 12];
|
|
+ } QEMU_PACKED redolog;
|
|
+ struct {
|
|
+ uint64_t disk; /* disk size */
|
|
+ char padding[HEADER_SIZE - 64 - 20 - 8];
|
|
+ } QEMU_PACKED redolog_v1;
|
|
+ char padding[HEADER_SIZE - 64 - 20];
|
|
} extra;
|
|
-};
|
|
+} QEMU_PACKED;
|
|
|
|
typedef struct BDRVBochsState {
|
|
CoMutex lock;
|
|
@@ -113,7 +98,6 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags)
|
|
BDRVBochsState *s = bs->opaque;
|
|
int i;
|
|
struct bochs_header bochs;
|
|
- struct bochs_header_v1 header_v1;
|
|
int ret;
|
|
|
|
bs->read_only = 1; // no write support yet
|
|
@@ -132,13 +116,12 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags)
|
|
}
|
|
|
|
if (le32_to_cpu(bochs.version) == HEADER_V1) {
|
|
- memcpy(&header_v1, &bochs, sizeof(bochs));
|
|
- bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
|
|
+ bs->total_sectors = le64_to_cpu(bochs.extra.redolog_v1.disk) / 512;
|
|
} else {
|
|
- bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
|
|
+ bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
|
|
}
|
|
|
|
- s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
|
|
+ s->catalog_size = le32_to_cpu(bochs.catalog);
|
|
s->catalog_bitmap = g_malloc(s->catalog_size * 4);
|
|
|
|
ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
|
|
@@ -152,10 +135,10 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags)
|
|
|
|
s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
|
|
|
|
- s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
|
|
- s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
|
|
+ s->bitmap_blocks = 1 + (le32_to_cpu(bochs.bitmap) - 1) / 512;
|
|
+ s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
|
|
|
|
- s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
|
|
+ s->extent_size = le32_to_cpu(bochs.extent);
|
|
|
|
qemu_co_mutex_init(&s->lock);
|
|
return 0;
|