From: "Daniel P. Berrange" <berrange(a)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