9ae3a8
From 99ad3018eac4089569f5ccbc84737dce8e92384f Mon Sep 17 00:00:00 2001
9ae3a8
From: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
Date: Wed, 31 Jul 2013 09:54:07 +0200
9ae3a8
Subject: vmdk: Allow reading variable size descriptor files
9ae3a8
9ae3a8
Message-id: <1374654509-5535-3-git-send-email-famz@redhat.com>
9ae3a8
Patchwork-id: 52674
9ae3a8
O-Subject: [RHEL-7 qemu-kvm PATCH 2/5] vmdk: Allow reading variable size descriptor files
9ae3a8
Bugzilla: 836675
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
9ae3a8
From: Evgeny Budilovsky <evgeny.budilovsky@ravellosystems.com>
9ae3a8
9ae3a8
the hard-coded 2k buffer on the stack won't allow reading big descriptor
9ae3a8
files which can be generated when storing big images. For example 500G
9ae3a8
vmdk splitted to 2G chunks.
9ae3a8
9ae3a8
Signed-off-by: Evgeny Budilovsky <evgeny.budilovsky@ravellosystems.com>
9ae3a8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 0bed087df24c7b3fae366f239b9d150de3309416)
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
9ae3a8
diff --git a/block/vmdk.c b/block/vmdk.c
9ae3a8
index ee50a73..65ae011 100644
9ae3a8
--- a/block/vmdk.c
9ae3a8
+++ b/block/vmdk.c
9ae3a8
@@ -722,27 +722,40 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
9ae3a8
                                int64_t desc_offset)
9ae3a8
 {
9ae3a8
     int ret;
9ae3a8
-    char buf[2048];
9ae3a8
+    char *buf = NULL;
9ae3a8
     char ct[128];
9ae3a8
     BDRVVmdkState *s = bs->opaque;
9ae3a8
+    int64_t size;
9ae3a8
 
9ae3a8
-    ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf));
9ae3a8
+    size = bdrv_getlength(bs->file);
9ae3a8
+    if (size < 0) {
9ae3a8
+        return -EINVAL;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    size = MIN(size, 1 << 20);  /* avoid unbounded allocation */
9ae3a8
+    buf = g_malloc0(size + 1);
9ae3a8
+
9ae3a8
+    ret = bdrv_pread(bs->file, desc_offset, buf, size);
9ae3a8
     if (ret < 0) {
9ae3a8
-        return ret;
9ae3a8
+        goto exit;
9ae3a8
     }
9ae3a8
-    buf[2047] = '\0';
9ae3a8
     if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
9ae3a8
-        return -EMEDIUMTYPE;
9ae3a8
+        ret = -EMEDIUMTYPE;
9ae3a8
+        goto exit;
9ae3a8
     }
9ae3a8
     if (strcmp(ct, "monolithicFlat") &&
9ae3a8
         strcmp(ct, "twoGbMaxExtentSparse") &&
9ae3a8
         strcmp(ct, "twoGbMaxExtentFlat")) {
9ae3a8
         fprintf(stderr,
9ae3a8
                 "VMDK: Not supported image type \"%s\""".\n", ct);
9ae3a8
-        return -ENOTSUP;
9ae3a8
+        ret = -ENOTSUP;
9ae3a8
+        goto exit;
9ae3a8
     }
9ae3a8
     s->desc_offset = 0;
9ae3a8
-    return vmdk_parse_extents(buf, bs, bs->file->filename);
9ae3a8
+    ret = vmdk_parse_extents(buf, bs, bs->file->filename);
9ae3a8
+exit:
9ae3a8
+    g_free(buf);
9ae3a8
+    return ret;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static int vmdk_open(BlockDriverState *bs, QDict *options, int flags)