mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 07:17:44 +00:00
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.
This commit is contained in:
parent
ae6135bf05
commit
87c39f0e20
@ -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, "<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)
|
||||
@ -9989,17 +10096,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",
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user