summaryrefslogtreecommitdiffstats
path: root/fish/virt.c
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2010-10-21 23:05:26 +0100
committerRichard W.M. Jones <rjones@redhat.com>2010-10-22 17:45:06 +0100
commit0c1d3c02a8147617ee0646e37d011235abdd2c22 (patch)
treeaa7a73c83c09065a00383431cc04052b74e73081 /fish/virt.c
parent14490c3e1aac61c6ac90f28828896683f64f0dc9 (diff)
downloadlibguestfs-0c1d3c02a8147617ee0646e37d011235abdd2c22.tar.gz
libguestfs-0c1d3c02a8147617ee0646e37d011235abdd2c22.tar.xz
libguestfs-0c1d3c02a8147617ee0646e37d011235abdd2c22.zip
fish: Specify format of disks (RHBZ#642934,CVE-2010-3851).
For libvirt guests, the disk format is copied from libvirt (if libvirt knows it). For command line disk images, you can use --format to override format auto-detection.
Diffstat (limited to 'fish/virt.c')
-rw-r--r--fish/virt.c111
1 files changed, 68 insertions, 43 deletions
diff --git a/fish/virt.c b/fish/virt.c
index 9c4ce1ad..d915d220 100644
--- a/fish/virt.c
+++ b/fish/virt.c
@@ -32,8 +32,6 @@
#include "fish.h"
-static int add_drives_from_node_set (xmlDocPtr doc, xmlNodeSetPtr nodes);
-
/* Implements the guts of the '-d' option.
*
* Note that we have to observe the '--ro' flag in two respects: by
@@ -56,7 +54,7 @@ add_libvirt_drives (const char *guest)
LIBXML_TEST_VERSION;
}
- int r = -1, nr_added = 0;
+ int r = -1, nr_added = 0, i;
virErrorPtr err;
virConnectPtr conn = NULL;
virDomainPtr dom = NULL;
@@ -121,25 +119,81 @@ add_libvirt_drives (const char *guest)
goto cleanup;
}
- xpathObj = xmlXPathEvalExpression (BAD_CAST "//devices/disk/source/@dev",
- xpathCtx);
+ /* This gives us a set of all the <disk> nodes. */
+ xpathObj = xmlXPathEvalExpression (BAD_CAST "//devices/disk", xpathCtx);
if (xpathObj == NULL) {
fprintf (stderr, _("guestfish: unable to evaluate XPath expression\n"));
goto cleanup;
}
- nr_added += add_drives_from_node_set (doc, xpathObj->nodesetval);
+ xmlNodeSetPtr nodes = xpathObj->nodesetval;
+ for (i = 0; i < nodes->nodeNr; ++i) {
+ xmlXPathObjectPtr xpfilename;
+ xmlXPathObjectPtr xpformat;
+
+ /* Change the context to the current <disk> node.
+ * DV advises to reset this before each search since older versions of
+ * libxml2 might overwrite it.
+ */
+ xpathCtx->node = nodes->nodeTab[i];
+
+ /* Filename can be in <source dev=..> or <source file=..> attribute. */
+ xpfilename = xmlXPathEvalExpression (BAD_CAST "./source/@dev", xpathCtx);
+ if (xpfilename == NULL ||
+ xpfilename->nodesetval == NULL ||
+ xpfilename->nodesetval->nodeNr == 0) {
+ xmlXPathFreeObject (xpfilename);
+ xpathCtx->node = nodes->nodeTab[i];
+ xpfilename = xmlXPathEvalExpression (BAD_CAST "./source/@file", xpathCtx);
+ if (xpfilename == NULL ||
+ xpfilename->nodesetval == NULL ||
+ xpfilename->nodesetval->nodeNr == 0) {
+ xmlXPathFreeObject (xpfilename);
+ continue; /* disk filename not found, skip this */
+ }
+ }
- xmlXPathFreeObject (xpathObj); xpathObj = NULL;
+ assert (xpfilename->nodesetval->nodeTab[0]);
+ assert (xpfilename->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE);
+ xmlAttrPtr attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
+ char *filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
+
+ /* Get the disk format (may not be set). */
+ xpathCtx->node = nodes->nodeTab[i];
+ xpformat = xmlXPathEvalExpression (BAD_CAST "./driver/@type", xpathCtx);
+ char *format = NULL;
+ if (xpformat != NULL &&
+ xpformat->nodesetval &&
+ xpformat->nodesetval->nodeNr > 0) {
+ assert (xpformat->nodesetval->nodeTab[0]);
+ assert (xpformat->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE);
+ attr = (xmlAttrPtr) xpformat->nodesetval->nodeTab[0];
+ format = (char *) xmlNodeListGetString (doc, attr->children, 1);
+ }
- xpathObj = xmlXPathEvalExpression (BAD_CAST "//devices/disk/source/@file",
- xpathCtx);
- if (xpathObj == NULL) {
- fprintf (stderr, _("guestfish: unable to evaluate XPath expression\n"));
- goto cleanup;
- }
+ /* Add the disk, with optional format. */
+ struct guestfs_add_drive_opts_argv optargs = { .bitmask = 0 };
+ if (read_only) {
+ optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
+ optargs.readonly = read_only;
+ }
+ if (format) {
+ optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
+ optargs.format = format;
+ }
+
+ int t = guestfs_add_drive_opts_argv (g, filename, &optargs);
+
+ xmlFree (filename);
+ xmlFree (format);
+ xmlXPathFreeObject (xpfilename);
+ xmlXPathFreeObject (xpformat);
+
+ if (t == -1)
+ goto cleanup;
- nr_added += add_drives_from_node_set (doc, xpathObj->nodesetval);
+ nr_added++;
+ }
if (nr_added == 0) {
fprintf (stderr, _("guestfish: libvirt domain '%s' has no disks\n"),
@@ -160,32 +214,3 @@ cleanup:
return r;
}
-
-static int
-add_drives_from_node_set (xmlDocPtr doc, xmlNodeSetPtr nodes)
-{
- if (!nodes)
- return 0;
-
- int i;
-
- for (i = 0; i < nodes->nodeNr; ++i) {
- assert (nodes->nodeTab[i]);
- assert (nodes->nodeTab[i]->type == XML_ATTRIBUTE_NODE);
- xmlAttrPtr attr = (xmlAttrPtr) nodes->nodeTab[i];
-
- char *device = (char *) xmlNodeListGetString (doc, attr->children, 1);
-
- int r;
- if (!read_only)
- r = guestfs_add_drive (g, device);
- else
- r = guestfs_add_drive_ro (g, device);
- if (r == -1)
- exit (EXIT_FAILURE);
-
- xmlFree (device);
- }
-
- return nodes->nodeNr;
-}