9ae3a8
From 30e78b5a6fc16e3669f83b27e02c8eb53e646b48 Mon Sep 17 00:00:00 2001
9ae3a8
From: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Date: Tue, 25 Mar 2014 14:23:17 +0100
9ae3a8
Subject: [PATCH 10/49] bochs: Unify header structs and make them QEMU_PACKED
9ae3a8
9ae3a8
RH-Author: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Message-id: <1395753835-7591-11-git-send-email-kwolf@redhat.com>
9ae3a8
Patchwork-id: n/a
9ae3a8
O-Subject: [virt-devel] [EMBARGOED RHEL-7.0 qemu-kvm PATCH 10/48] bochs: Unify header structs and make them QEMU_PACKED
9ae3a8
Bugzilla: 1066691
9ae3a8
RH-Acked-by: Jeff Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
9ae3a8
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1066691
9ae3a8
Upstream status: Series embargoed
9ae3a8
9ae3a8
This is an on-disk structure, so offsets must be accurate.
9ae3a8
9ae3a8
Before this patch, sizeof(bochs) != sizeof(header_v1), which makes the
9ae3a8
memcpy() between both invalid. We're lucky enough that the destination
9ae3a8
buffer happened to be the larger one, and the memcpy size to be taken
9ae3a8
from the smaller one, so we didn't get a buffer overflow in practice.
9ae3a8
9ae3a8
This patch unifies the both structures, eliminating the need to do a
9ae3a8
memcpy in the first place. The common fields are extracted to the top
9ae3a8
level of the struct and the actually differing part gets a union of the
9ae3a8
two versions.
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
---
9ae3a8
 block/bochs.c |   67 +++++++++++++++++++++-----------------------------------
9ae3a8
 1 files changed, 25 insertions(+), 42 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/bochs.c b/block/bochs.c
9ae3a8
index 51d9a90..708780d 100644
9ae3a8
--- a/block/bochs.c
9ae3a8
+++ b/block/bochs.c
9ae3a8
@@ -39,45 +39,30 @@
9ae3a8
 // not allocated: 0xffffffff
9ae3a8
 
9ae3a8
 // always little-endian
9ae3a8
-struct bochs_header_v1 {
9ae3a8
-    char magic[32]; // "Bochs Virtual HD Image"
9ae3a8
-    char type[16]; // "Redolog"
9ae3a8
-    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
9ae3a8
-    uint32_t version;
9ae3a8
-    uint32_t header; // size of header
9ae3a8
-
9ae3a8
-    union {
9ae3a8
-	struct {
9ae3a8
-	    uint32_t catalog; // num of entries
9ae3a8
-	    uint32_t bitmap; // bitmap size
9ae3a8
-	    uint32_t extent; // extent size
9ae3a8
-	    uint64_t disk; // disk size
9ae3a8
-	    char padding[HEADER_SIZE - 64 - 8 - 20];
9ae3a8
-	} redolog;
9ae3a8
-	char padding[HEADER_SIZE - 64 - 8];
9ae3a8
-    } extra;
9ae3a8
-};
9ae3a8
-
9ae3a8
-// always little-endian
9ae3a8
 struct bochs_header {
9ae3a8
-    char magic[32]; // "Bochs Virtual HD Image"
9ae3a8
-    char type[16]; // "Redolog"
9ae3a8
-    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
9ae3a8
+    char magic[32];     /* "Bochs Virtual HD Image" */
9ae3a8
+    char type[16];      /* "Redolog" */
9ae3a8
+    char subtype[16];   /* "Undoable" / "Volatile" / "Growing" */
9ae3a8
     uint32_t version;
9ae3a8
-    uint32_t header; // size of header
9ae3a8
+    uint32_t header;    /* size of header */
9ae3a8
+
9ae3a8
+    uint32_t catalog;   /* num of entries */
9ae3a8
+    uint32_t bitmap;    /* bitmap size */
9ae3a8
+    uint32_t extent;    /* extent size */
9ae3a8
 
9ae3a8
     union {
9ae3a8
-	struct {
9ae3a8
-	    uint32_t catalog; // num of entries
9ae3a8
-	    uint32_t bitmap; // bitmap size
9ae3a8
-	    uint32_t extent; // extent size
9ae3a8
-	    uint32_t reserved; // for ???
9ae3a8
-	    uint64_t disk; // disk size
9ae3a8
-	    char padding[HEADER_SIZE - 64 - 8 - 24];
9ae3a8
-	} redolog;
9ae3a8
-	char padding[HEADER_SIZE - 64 - 8];
9ae3a8
+        struct {
9ae3a8
+            uint32_t reserved;  /* for ??? */
9ae3a8
+            uint64_t disk;      /* disk size */
9ae3a8
+            char padding[HEADER_SIZE - 64 - 20 - 12];
9ae3a8
+        } QEMU_PACKED redolog;
9ae3a8
+        struct {
9ae3a8
+            uint64_t disk;      /* disk size */
9ae3a8
+            char padding[HEADER_SIZE - 64 - 20 - 8];
9ae3a8
+        } QEMU_PACKED redolog_v1;
9ae3a8
+        char padding[HEADER_SIZE - 64 - 20];
9ae3a8
     } extra;
9ae3a8
-};
9ae3a8
+} QEMU_PACKED;
9ae3a8
 
9ae3a8
 typedef struct BDRVBochsState {
9ae3a8
     CoMutex lock;
9ae3a8
@@ -114,7 +99,6 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     BDRVBochsState *s = bs->opaque;
9ae3a8
     int i;
9ae3a8
     struct bochs_header bochs;
9ae3a8
-    struct bochs_header_v1 header_v1;
9ae3a8
     int ret;
9ae3a8
 
9ae3a8
     bs->read_only = 1; // no write support yet
9ae3a8
@@ -133,13 +117,12 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     }
9ae3a8
 
9ae3a8
     if (le32_to_cpu(bochs.version) == HEADER_V1) {
9ae3a8
-      memcpy(&header_v1, &bochs, sizeof(bochs));
9ae3a8
-      bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
9ae3a8
+        bs->total_sectors = le64_to_cpu(bochs.extra.redolog_v1.disk) / 512;
9ae3a8
     } else {
9ae3a8
-      bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
9ae3a8
+        bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
9ae3a8
+    s->catalog_size = le32_to_cpu(bochs.catalog);
9ae3a8
     s->catalog_bitmap = g_malloc(s->catalog_size * 4);
9ae3a8
 
9ae3a8
     ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
9ae3a8
@@ -153,10 +136,10 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
 
9ae3a8
     s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
9ae3a8
 
9ae3a8
-    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
9ae3a8
-    s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
9ae3a8
+    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.bitmap) - 1) / 512;
9ae3a8
+    s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
9ae3a8
 
9ae3a8
-    s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
9ae3a8
+    s->extent_size = le32_to_cpu(bochs.extent);
9ae3a8
 
9ae3a8
     qemu_co_mutex_init(&s->lock);
9ae3a8
     return 0;
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8