9119d9
From d4419813040b7acccda8b637ac26c67912cb747f Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <d4419813040b7acccda8b637ac26c67912cb747f@dist-git>
9119d9
From: Peter Krempa <pkrempa@redhat.com>
9119d9
Date: Wed, 29 Oct 2014 18:04:09 +0100
9119d9
Subject: [PATCH] storage: Fix crash when parsing backing store URI with schema
9119d9
9119d9
The code that parses the schema from the URI touches the "hosts[0]"
9119d9
member of the storage file source structure in case the URI contains a
9119d9
schema. The hosts array was not yet allocated at the point in the code
9119d9
where the transport protocol was parsed and set. This lead to a crash of
9119d9
libvirtd.
9119d9
9119d9
Fix the code by allocating the "hosts" array upfront and add a test case
9119d9
to verify this scenario. (Unfortunately this requires shuffling the test
9119d9
case numbers too).
9119d9
9119d9
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1156288
9119d9
(cherry picked from commit 98784369fd52ed6aa9bab2a9a9d213c52019e6ee)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/util/virstoragefile.c | 10 +++++-----
9119d9
 tests/virstoragetest.c    | 31 +++++++++++++++++++++++++------
9119d9
 2 files changed, 30 insertions(+), 11 deletions(-)
9119d9
9119d9
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
9119d9
index fdf14c0..6e6ee08 100644
9119d9
--- a/src/util/virstoragefile.c
9119d9
+++ b/src/util/virstoragefile.c
9119d9
@@ -2111,6 +2111,11 @@ virStorageSourceParseBackingURI(virStorageSourcePtr src,
9119d9
         goto cleanup;
9119d9
     }
9119d9
 
9119d9
+    if (VIR_ALLOC(src->hosts) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    src->nhosts = 1;
9119d9
+
9119d9
     if (!(scheme = virStringSplit(uri->scheme, "+", 2)))
9119d9
         goto cleanup;
9119d9
 
9119d9
@@ -2161,11 +2166,6 @@ virStorageSourceParseBackingURI(virStorageSourcePtr src,
9119d9
         tmp[0] = '\0';
9119d9
     }
9119d9
 
9119d9
-    if (VIR_ALLOC(src->hosts) < 0)
9119d9
-        goto cleanup;
9119d9
-
9119d9
-    src->nhosts = 1;
9119d9
-
9119d9
     if (uri->port > 0) {
9119d9
         if (virAsprintf(&src->hosts->port, "%d", uri->port) < 0)
9119d9
             goto cleanup;
9119d9
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
9119d9
index 29f5c7a..05e48f3 100644
9119d9
--- a/tests/virstoragetest.c
9119d9
+++ b/tests/virstoragetest.c
9119d9
@@ -835,6 +835,25 @@ mymain(void)
9119d9
                (&qcow2, &nbd), EXP_PASS,
9119d9
                (&qcow2, &nbd), ALLOW_PROBE | EXP_PASS);
9119d9
 
9119d9
+    /* Rewrite qcow2 to use an nbd: protocol as backend */
9119d9
+    virCommandFree(cmd);
9119d9
+    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
9119d9
+                               "-F", "raw", "-b", "nbd+tcp://example.org:6000/blah",
9119d9
+                               "qcow2", NULL);
9119d9
+    if (virCommandRun(cmd, NULL) < 0)
9119d9
+        ret = -1;
9119d9
+    qcow2.expBackingStoreRaw = "nbd+tcp://example.org:6000/blah";
9119d9
+
9119d9
+    /* Qcow2 file with backing protocol instead of file */
9119d9
+    testFileData nbd2 = {
9119d9
+        .path = "blah",
9119d9
+        .type = VIR_STORAGE_TYPE_NETWORK,
9119d9
+        .format = VIR_STORAGE_FILE_RAW,
9119d9
+    };
9119d9
+    TEST_CHAIN(12, absqcow2, VIR_STORAGE_FILE_QCOW2,
9119d9
+               (&qcow2, &nbd2), EXP_PASS,
9119d9
+               (&qcow2, &nbd2), ALLOW_PROBE | EXP_PASS);
9119d9
+
9119d9
     /* qed file */
9119d9
     testFileData qed = {
9119d9
         .expBackingStoreRaw = absraw,
9119d9
@@ -848,7 +867,7 @@ mymain(void)
9119d9
         .type = VIR_STORAGE_TYPE_FILE,
9119d9
         .format = VIR_STORAGE_FILE_RAW,
9119d9
     };
9119d9
-    TEST_CHAIN(12, absqed, VIR_STORAGE_FILE_AUTO,
9119d9
+    TEST_CHAIN(13, absqed, VIR_STORAGE_FILE_AUTO,
9119d9
                (&qed_as_raw), EXP_PASS,
9119d9
                (&qed, &raw), ALLOW_PROBE | EXP_PASS);
9119d9
 
9119d9
@@ -858,10 +877,10 @@ mymain(void)
9119d9
         .type = VIR_STORAGE_TYPE_DIR,
9119d9
         .format = VIR_STORAGE_FILE_DIR,
9119d9
     };
9119d9
-    TEST_CHAIN(13, absdir, VIR_STORAGE_FILE_AUTO,
9119d9
+    TEST_CHAIN(14, absdir, VIR_STORAGE_FILE_AUTO,
9119d9
                (&dir), EXP_PASS,
9119d9
                (&dir), ALLOW_PROBE | EXP_PASS);
9119d9
-    TEST_CHAIN(14, absdir, VIR_STORAGE_FILE_DIR,
9119d9
+    TEST_CHAIN(15, absdir, VIR_STORAGE_FILE_DIR,
9119d9
                (&dir), EXP_PASS,
9119d9
                (&dir), ALLOW_PROBE | EXP_PASS);
9119d9
 
9119d9
@@ -900,7 +919,7 @@ mymain(void)
9119d9
 
9119d9
     raw.path = datadir "/sub/../sub/../raw";
9119d9
     raw.pathRel = "../raw";
9119d9
-    TEST_CHAIN(15, abslink2, VIR_STORAGE_FILE_QCOW2,
9119d9
+    TEST_CHAIN(16, abslink2, VIR_STORAGE_FILE_QCOW2,
9119d9
                (&link2, &link1, &raw), EXP_PASS,
9119d9
                (&link2, &link1, &raw), ALLOW_PROBE | EXP_PASS);
9119d9
 #endif
9119d9
@@ -914,7 +933,7 @@ mymain(void)
9119d9
     qcow2.expBackingStoreRaw = "qcow2";
9119d9
 
9119d9
     /* Behavior of an infinite loop chain */
9119d9
-    TEST_CHAIN(16, absqcow2, VIR_STORAGE_FILE_QCOW2,
9119d9
+    TEST_CHAIN(17, absqcow2, VIR_STORAGE_FILE_QCOW2,
9119d9
                (&qcow2), EXP_WARN,
9119d9
                (&qcow2), ALLOW_PROBE | EXP_WARN);
9119d9
 
9119d9
@@ -933,7 +952,7 @@ mymain(void)
9119d9
     qcow2.expBackingStoreRaw = "wrap";
9119d9
 
9119d9
     /* Behavior of an infinite loop chain */
9119d9
-    TEST_CHAIN(17, abswrap, VIR_STORAGE_FILE_QCOW2,
9119d9
+    TEST_CHAIN(18, abswrap, VIR_STORAGE_FILE_QCOW2,
9119d9
                (&wrap, &qcow2), EXP_WARN,
9119d9
                (&wrap, &qcow2), ALLOW_PROBE | EXP_WARN);
9119d9
 
9119d9
-- 
9119d9
2.1.3
9119d9