From 87c39f0e20a2e3f64398b6ed926c3dc0b0455f5e Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 25 Jan 2012 14:12:51 +0000 Subject: [PATCH] Re-add domain device seclabel parsing / formatting 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 6a6d2eced3..aba81c305e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -812,6 +812,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; @@ -890,6 +901,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); @@ -2666,6 +2679,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 @@ -2747,9 +2821,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; @@ -2808,6 +2884,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"); @@ -3057,6 +3135,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); @@ -6413,7 +6502,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; @@ -7523,6 +7612,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, nodes[i], ctxt, bootMap, + &def->seclabel, flags); if (!disk) goto error; @@ -9867,6 +9957,23 @@ cleanup: } +static void +virSecurityDeviceLabelDefFormat(virBufferPtr buf, + virSecurityDeviceLabelDefPtr def) +{ + virBufferAsprintf(buf, "norelabel ? "no" : "yes"); + if (def->label) { + virBufferAddLit(buf, ">\n"); + virBufferEscapeString(buf, " \n", + def->label); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } +} + + static int virDomainLeaseDefFormat(virBufferPtr buf, virDomainLeaseDefPtr def) @@ -9989,17 +10096,34 @@ virDomainDiskDefFormat(virBufferPtr buf, def->startupPolicy) { switch (def->type) { case VIR_DOMAIN_DISK_TYPE_FILE: - virBufferAsprintf(buf," 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, " \n"); + } else { + virBufferAddLit(buf, "/>\n"); + } break; case VIR_DOMAIN_DISK_TYPE_BLOCK: - virBufferEscapeString(buf, " \n", + virBufferEscapeString(buf, " src); + if (def->seclabel) { + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 8); + virSecurityDeviceLabelDefFormat(buf, def->seclabel); + virBufferAdjustIndent(buf, -8); + virBufferAddLit(buf, " \n"); + } else { + virBufferAddLit(buf, "/>\n"); + } break; case VIR_DOMAIN_DISK_TYPE_DIR: virBufferEscapeString(buf, " \n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index acb936e69c..a604155319 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -193,6 +193,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 { @@ -380,7 +390,7 @@ struct _virDomainDiskDef { int device; int bus; char *src; - virSecurityLabelDefPtr seclabel; + virSecurityDeviceLabelDefPtr seclabel; char *dst; int protocol; int nhosts;