[libvirt] [PATCH v2 2/5] Re-add domain device seclabel parsing / formatting

Daniel P. Berrange berrange at redhat.com
Wed Jan 25 14:12:51 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

This re-introduces parsing & formatting for per device seclabels.
There is a new virDomainDeviceSeclabelPtr struct and corresponding
APIs for parsing/formatting.
---
 src/conf/domain_conf.c |  132 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/conf/domain_conf.h |   12 ++++-
 2 files changed, 139 insertions(+), 5 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6c67cd8..8eacc1f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -809,6 +809,17 @@ virSecurityLabelDefClear(virSecurityLabelDefPtr def)
     VIR_FREE(def->baselabel);
 }
 
+
+static void
+virSecurityDeviceLabelDefFree(virSecurityDeviceLabelDefPtr def)
+{
+    if (!def)
+        return;
+    VIR_FREE(def->label);
+    VIR_FREE(def);
+}
+
+
 void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
 {
     int ii;
@@ -887,6 +898,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
     virStorageEncryptionFree(def->encryption);
     virDomainDeviceInfoClear(&def->info);
 
+    virSecurityDeviceLabelDefFree(def->seclabel);
+
     for (i = 0 ; i < def->nhosts ; i++)
         virDomainDiskHostDefFree(&def->hosts[i]);
     VIR_FREE(def->hosts);
@@ -2609,6 +2622,67 @@ error:
     return -1;
 }
 
+
+static int
+virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr *def,
+                                  virSecurityLabelDefPtr vmDef,
+                                  xmlXPathContextPtr ctxt)
+{
+    char *p;
+
+    *def = NULL;
+
+    if (virXPathNode("./seclabel", ctxt) == NULL)
+        return 0;
+
+    /* Can't use overrides if top-level doesn't allow relabeling.  */
+    if (vmDef && vmDef->norelabel) {
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+                             _("label overrides require relabeling to be "
+                               "enabled at the domain level"));
+        return -1;
+    }
+
+    if (VIR_ALLOC(*def) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    p = virXPathStringLimit("string(./seclabel/@relabel)",
+                            VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
+    if (p != NULL) {
+        if (STREQ(p, "yes")) {
+            (*def)->norelabel = false;
+        } else if (STREQ(p, "no")) {
+            (*def)->norelabel = true;
+        } else {
+            virDomainReportError(VIR_ERR_XML_ERROR,
+                                 _("invalid security relabel value %s"), p);
+            VIR_FREE(p);
+            VIR_FREE(*def);
+            return -1;
+        }
+        VIR_FREE(p);
+    } else {
+        (*def)->norelabel = false;
+    }
+
+    p = virXPathStringLimit("string(./seclabel/label[1])",
+                            VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
+    (*def)->label = p;
+
+    if ((*def)->label && (*def)->norelabel) {
+        virDomainReportError(VIR_ERR_XML_ERROR,
+                             _("Cannot specify a label if relabelling is turned off"));
+        VIR_FREE((*def)->label);
+        VIR_FREE(*def);
+        return -1;
+    }
+
+    return 0;
+}
+
+
 /* Parse the XML definition for a lease
  */
 static virDomainLeaseDefPtr
@@ -2690,9 +2764,11 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                          xmlNodePtr node,
                          xmlXPathContextPtr ctxt,
                          virBitmapPtr bootMap,
+                         virSecurityLabelDefPtr vmSeclabel,
                          unsigned int flags)
 {
     virDomainDiskDefPtr def;
+    xmlNodePtr sourceNode = NULL;
     xmlNodePtr cur, child;
     xmlNodePtr save_ctxt = ctxt->node;
     char *type = NULL;
@@ -2748,6 +2824,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
             if ((source == NULL && hosts == NULL) &&
                 (xmlStrEqual(cur->name, BAD_CAST "source"))) {
 
+                sourceNode = cur;
+
                 switch (def->type) {
                 case VIR_DOMAIN_DISK_TYPE_FILE:
                     source = virXMLPropString(cur, "file");
@@ -2999,6 +3077,17 @@ virDomainDiskDefParseXML(virCapsPtr caps,
         goto error;
     }
 
+    /* If source is present, check for an optional seclabel override.  */
+    if (sourceNode) {
+        xmlNodePtr saved_node = ctxt->node;
+        ctxt->node = sourceNode;
+        if (virSecurityDeviceLabelDefParseXML(&def->seclabel,
+                                              vmSeclabel,
+                                              ctxt) < 0)
+            goto error;
+        ctxt->node = saved_node;
+    }
+
     if (target == NULL) {
         virDomainReportError(VIR_ERR_NO_TARGET,
                              source ? "%s" : NULL, source);
@@ -6346,7 +6435,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
     if (xmlStrEqual(node->name, BAD_CAST "disk")) {
         dev->type = VIR_DOMAIN_DEVICE_DISK;
         if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, ctxt,
-                                                        NULL, flags)))
+                                                        NULL, &def->seclabel, flags)))
             goto error;
     } else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
         dev->type = VIR_DOMAIN_DEVICE_LEASE;
@@ -7448,6 +7537,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
                                                             nodes[i],
                                                             ctxt,
                                                             bootMap,
+                                                            &def->seclabel,
                                                             flags);
         if (!disk)
             goto error;
@@ -9792,6 +9882,23 @@ cleanup:
 }
 
 
+static void
+virSecurityDeviceLabelDefFormat(virBufferPtr buf,
+                                virSecurityDeviceLabelDefPtr def)
+{
+    virBufferAsprintf(buf, "<seclabel relabel='%s'",
+                      def->norelabel ? "no" : "yes");
+    if (def->label) {
+        virBufferAddLit(buf, ">\n");
+        virBufferEscapeString(buf, "  <label>%s</label>\n",
+                              def->label);
+        virBufferAddLit(buf, "</seclabel>\n");
+    } else {
+        virBufferAddLit(buf, "/>\n");
+    }
+}
+
+
 static int
 virDomainLeaseDefFormat(virBufferPtr buf,
                         virDomainLeaseDefPtr def)
@@ -9907,17 +10014,34 @@ virDomainDiskDefFormat(virBufferPtr buf,
         def->startupPolicy) {
         switch (def->type) {
         case VIR_DOMAIN_DISK_TYPE_FILE:
-            virBufferAsprintf(buf,"      <source");
+            virBufferAddLit(buf,"      <source");
             if (def->src)
                 virBufferEscapeString(buf, " file='%s'", def->src);
             if (def->startupPolicy)
                 virBufferEscapeString(buf, " startupPolicy='%s'",
                                       startupPolicy);
-            virBufferAsprintf(buf, "/>\n");
+            if (def->seclabel) {
+                virBufferAddLit(buf, ">\n");
+                virBufferAdjustIndent(buf, 8);
+                virSecurityDeviceLabelDefFormat(buf, def->seclabel);
+                virBufferAdjustIndent(buf, -8);
+                virBufferAddLit(buf, "      </source>\n");
+            } else {
+                virBufferAddLit(buf, "/>\n");
+            }
             break;
         case VIR_DOMAIN_DISK_TYPE_BLOCK:
-            virBufferEscapeString(buf, "      <source dev='%s'/>\n",
+            virBufferEscapeString(buf, "      <source dev='%s'",
                                   def->src);
+            if (def->seclabel) {
+                virBufferAddLit(buf, ">\n");
+                virBufferAdjustIndent(buf, 8);
+                virSecurityDeviceLabelDefFormat(buf, def->seclabel);
+                virBufferAdjustIndent(buf, -8);
+                virBufferAddLit(buf, "      </source>\n");
+            } else {
+                virBufferAddLit(buf, "/>\n");
+            }
             break;
         case VIR_DOMAIN_DISK_TYPE_DIR:
             virBufferEscapeString(buf, "      <source dir='%s'/>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3b522a9..2d31fd3 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -180,6 +180,16 @@ struct _virSecurityLabelDef {
     bool norelabel;
 };
 
+
+/* Security configuration for domain */
+typedef struct _virSecurityDeviceLabelDef virSecurityDeviceLabelDef;
+typedef virSecurityDeviceLabelDef *virSecurityDeviceLabelDefPtr;
+struct _virSecurityDeviceLabelDef {
+    char *label;        /* image label string */
+    bool norelabel;
+};
+
+
 typedef struct _virDomainHostdevOrigStates virDomainHostdevOrigStates;
 typedef virDomainHostdevOrigStates *virDomainHostdevOrigStatesPtr;
 struct _virDomainHostdevOrigStates {
@@ -367,7 +377,7 @@ struct _virDomainDiskDef {
     int device;
     int bus;
     char *src;
-    virSecurityLabelDefPtr seclabel;
+    virSecurityDeviceLabelDefPtr seclabel;
     char *dst;
     int protocol;
     int nhosts;
-- 
1.7.7.5




More information about the libvir-list mailing list