mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-08 04:31:33 +00:00
Multiple security drivers in XML data
This patch updates the domain and capability XML parser and formatter to support more than one "seclabel" element for each domain and device. The RNG schema and the tests related to this are also updated by this patch. Signed-off-by: Marcelo Cerri <mhcerri@linux.vnet.ibm.com>
This commit is contained in:
parent
6c3cf57d6c
commit
e9377dda36
@ -1275,8 +1275,8 @@
|
|||||||
path to the file holding the disk. If the disk
|
path to the file holding the disk. If the disk
|
||||||
<code>type</code> is "block", then the <code>dev</code>
|
<code>type</code> is "block", then the <code>dev</code>
|
||||||
attribute specifies the path to the host device to serve as
|
attribute specifies the path to the host device to serve as
|
||||||
the disk. With both "file" and "block", an optional
|
the disk. With both "file" and "block", one or more optional
|
||||||
sub-element <code>seclabel</code>, <a href="#seclabel">described
|
sub-elements <code>seclabel</code>, <a href="#seclabel">described
|
||||||
below</a> (and <span class="since">since 0.9.9</span>), can be
|
below</a> (and <span class="since">since 0.9.9</span>), can be
|
||||||
used to override the domain security labeling policy for just
|
used to override the domain security labeling policy for just
|
||||||
that source file. If the disk <code>type</code> is "dir", then the
|
that source file. If the disk <code>type</code> is "dir", then the
|
||||||
@ -3919,6 +3919,13 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
since 0.6.2, and 'none' since 0.9.10.</span>
|
since 0.6.2, and 'none' since 0.9.10.</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If more than one security driver is used by libvirt, multiple
|
||||||
|
<code>seclabel</code> tags can be used, one for each driver and
|
||||||
|
the security driver referenced by each tag can be defined using
|
||||||
|
the attribute <code>model</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Valid input XML configurations for the top-level security label
|
Valid input XML configurations for the top-level security label
|
||||||
are:
|
are:
|
||||||
|
@ -44,20 +44,22 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<ref name='topology'/>
|
<ref name='topology'/>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<zeroOrMore>
|
||||||
<ref name='secmodel'/>
|
<ref name='secmodel'/>
|
||||||
</optional>
|
</zeroOrMore>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name='secmodel'>
|
<define name='secmodel'>
|
||||||
<element name='secmodel'>
|
<element name='secmodel'>
|
||||||
|
<interleave>
|
||||||
<element name='model'>
|
<element name='model'>
|
||||||
<text/>
|
<text/>
|
||||||
</element>
|
</element>
|
||||||
<element name='doi'>
|
<element name='doi'>
|
||||||
<text/>
|
<text/>
|
||||||
</element>
|
</element>
|
||||||
|
</interleave>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<ref name="devices"/>
|
<ref name="devices"/>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<zeroOrMore>
|
||||||
<ref name="seclabel"/>
|
<ref name="seclabel"/>
|
||||||
</optional>
|
</zeroOrMore>
|
||||||
<optional>
|
<optional>
|
||||||
<ref name='qemucmdline'/>
|
<ref name='qemucmdline'/>
|
||||||
</optional>
|
</optional>
|
||||||
@ -148,18 +148,32 @@
|
|||||||
<!-- A per-device seclabel override is more limited, either
|
<!-- A per-device seclabel override is more limited, either
|
||||||
relabel=no or a <label> must be present. -->
|
relabel=no or a <label> must be present. -->
|
||||||
<choice>
|
<choice>
|
||||||
|
<group>
|
||||||
|
<optional>
|
||||||
|
<attribute name='model'>
|
||||||
|
<text/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<attribute name='relabel'>
|
<attribute name='relabel'>
|
||||||
<value>no</value>
|
<value>no</value>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
</group>
|
||||||
<group>
|
<group>
|
||||||
|
<optional>
|
||||||
|
<attribute name='model'>
|
||||||
|
<text/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name='relabel'>
|
<attribute name='relabel'>
|
||||||
<value>yes</value>
|
<value>yes</value>
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
|
<zeroOrMore>
|
||||||
<element name='label'>
|
<element name='label'>
|
||||||
<text/>
|
<text/>
|
||||||
</element>
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
</group>
|
</group>
|
||||||
</choice>
|
</choice>
|
||||||
</element>
|
</element>
|
||||||
|
@ -772,12 +772,12 @@ virCapabilitiesFormatXML(virCapsPtr caps)
|
|||||||
virBufferAddLit(&xml, " </topology>\n");
|
virBufferAddLit(&xml, " </topology>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caps->host.nsecModels) {
|
for (i = 0; i < caps->host.nsecModels; i++) {
|
||||||
virBufferAddLit(&xml, " <secmodel>\n");
|
virBufferAddLit(&xml, " <secmodel>\n");
|
||||||
virBufferAsprintf(&xml, " <model>%s</model>\n",
|
virBufferAsprintf(&xml, " <model>%s</model>\n",
|
||||||
caps->host.secModels[0].model);
|
caps->host.secModels[i].model);
|
||||||
virBufferAsprintf(&xml, " <doi>%s</doi>\n",
|
virBufferAsprintf(&xml, " <doi>%s</doi>\n",
|
||||||
caps->host.secModels[0].doi);
|
caps->host.secModels[i].doi);
|
||||||
virBufferAddLit(&xml, " </secmodel>\n");
|
virBufferAddLit(&xml, " </secmodel>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2985,17 +2985,19 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static virSecurityLabelDefPtr
|
||||||
virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
|
virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,
|
||||||
xmlXPathContextPtr ctxt,
|
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
virSecurityLabelDefPtr def = NULL;
|
||||||
|
|
||||||
if (virXPathNode("./seclabel[1]", ctxt) == NULL)
|
if (VIR_ALLOC(def) < 0) {
|
||||||
return 0;
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/@type)",
|
p = virXPathStringLimit("string(./@type)",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
def->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
|
def->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
|
||||||
@ -3009,7 +3011,7 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/@relabel)",
|
p = virXPathStringLimit("string(./@relabel)",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
if (STREQ(p, "yes")) {
|
if (STREQ(p, "yes")) {
|
||||||
@ -3049,7 +3051,7 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
|
|||||||
if (def->type == VIR_DOMAIN_SECLABEL_STATIC ||
|
if (def->type == VIR_DOMAIN_SECLABEL_STATIC ||
|
||||||
(!(flags & VIR_DOMAIN_XML_INACTIVE) &&
|
(!(flags & VIR_DOMAIN_XML_INACTIVE) &&
|
||||||
def->type != VIR_DOMAIN_SECLABEL_NONE)) {
|
def->type != VIR_DOMAIN_SECLABEL_NONE)) {
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/label[1])",
|
p = virXPathStringLimit("string(./label[1])",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
@ -3064,7 +3066,7 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
|
|||||||
if (!def->norelabel &&
|
if (!def->norelabel &&
|
||||||
(!(flags & VIR_DOMAIN_XML_INACTIVE) &&
|
(!(flags & VIR_DOMAIN_XML_INACTIVE) &&
|
||||||
def->type != VIR_DOMAIN_SECLABEL_NONE)) {
|
def->type != VIR_DOMAIN_SECLABEL_NONE)) {
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/imagelabel[1])",
|
p = virXPathStringLimit("string(./imagelabel[1])",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
@ -3076,93 +3078,179 @@ virSecurityLabelDefParseXML(virSecurityLabelDefPtr def,
|
|||||||
|
|
||||||
/* Only parse baselabel for dynamic label type */
|
/* Only parse baselabel for dynamic label type */
|
||||||
if (def->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
|
if (def->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/baselabel[1])",
|
p = virXPathStringLimit("string(./baselabel[1])",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
def->baselabel = p;
|
def->baselabel = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only parse model, if static labelling, or a base
|
/* Always parse model */
|
||||||
* label is set, or doing active XML
|
p = virXPathStringLimit("string(./@model)",
|
||||||
*/
|
|
||||||
if (def->type == VIR_DOMAIN_SECLABEL_STATIC ||
|
|
||||||
def->baselabel ||
|
|
||||||
(!(flags & VIR_DOMAIN_XML_INACTIVE) &&
|
|
||||||
def->type != VIR_DOMAIN_SECLABEL_NONE)) {
|
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/@model)",
|
|
||||||
VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
|
||||||
if (p == NULL) {
|
if (p == NULL && def->type != VIR_DOMAIN_SECLABEL_NONE) {
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
"%s", _("missing security model"));
|
"%s", _("missing security model"));
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
def->model = p;
|
def->model = p;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return def;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
virSecurityLabelDefFree(def);
|
virSecurityLabelDefFree(def);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virSecurityLabelDefsParseXML(virDomainDefPtr def,
|
||||||
|
xmlXPathContextPtr ctxt,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int i = 0, n;
|
||||||
|
xmlNodePtr *list = NULL, saved_node;
|
||||||
|
|
||||||
|
/* Check args and save context */
|
||||||
|
if (def == NULL || ctxt == NULL)
|
||||||
|
return 0;
|
||||||
|
saved_node = ctxt->node;
|
||||||
|
|
||||||
|
/* Allocate a security labels based on XML */
|
||||||
|
if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(def->seclabels, n) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse each "seclabel" tag */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
ctxt->node = list[i];
|
||||||
|
def->seclabels[i] = virSecurityLabelDefParseXML(ctxt, flags);
|
||||||
|
if (def->seclabels[i] == NULL)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
def->nseclabels = n;
|
||||||
|
ctxt->node = saved_node;
|
||||||
|
VIR_FREE(list);
|
||||||
|
|
||||||
|
/* Checking missing model information
|
||||||
|
* when there is more than one seclabel */
|
||||||
|
if (n > 1) {
|
||||||
|
for(; n; n--) {
|
||||||
|
if (def->seclabels[n - 1]->model == NULL) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("missing security model "
|
||||||
|
"when using multiple labels"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ctxt->node = saved_node;
|
||||||
|
for (; i > 0; i--) {
|
||||||
|
virSecurityLabelDefFree(def->seclabels[i - 1]);
|
||||||
|
}
|
||||||
|
VIR_FREE(def->seclabels);
|
||||||
|
VIR_FREE(list);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr *def,
|
virSecurityDeviceLabelDefParseXML(virDomainDiskDefPtr def,
|
||||||
virSecurityLabelDefPtr vmDef,
|
virSecurityLabelDefPtr *vmSeclabels,
|
||||||
xmlXPathContextPtr ctxt)
|
int nvmSeclabels, xmlXPathContextPtr ctxt)
|
||||||
{
|
{
|
||||||
char *p;
|
int n, i, j;
|
||||||
|
xmlNodePtr *list = NULL;
|
||||||
|
virSecurityLabelDefPtr vmDef = NULL;
|
||||||
|
char *model, *relabel, *label;
|
||||||
|
|
||||||
*def = NULL;
|
if (def == NULL)
|
||||||
|
|
||||||
if (virXPathNode("./seclabel[1]", ctxt) == NULL)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
def->nseclabels = n;
|
||||||
|
if (VIR_ALLOC_N(def->seclabels, n) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (VIR_ALLOC(def->seclabels[i]) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
/* get model associated to this override */
|
||||||
|
model = virXMLPropString(list[i], "model");
|
||||||
|
if (model == NULL) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("invalid security model"));
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
/* find the security label that it's being overriden */
|
||||||
|
for (j = 0; j < nvmSeclabels; j++) {
|
||||||
|
if (STREQ(vmSeclabels[j]->model, model)) {
|
||||||
|
vmDef = vmSeclabels[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def->seclabels[i]->model = model;
|
||||||
|
}
|
||||||
|
|
||||||
/* Can't use overrides if top-level doesn't allow relabeling. */
|
/* Can't use overrides if top-level doesn't allow relabeling. */
|
||||||
if (vmDef && vmDef->norelabel) {
|
if (vmDef && vmDef->norelabel) {
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
_("label overrides require relabeling to be "
|
_("label overrides require relabeling to be "
|
||||||
"enabled at the domain level"));
|
"enabled at the domain level"));
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC(*def) < 0) {
|
relabel = virXMLPropString(list[i], "relabel");
|
||||||
virReportOOMError();
|
if (relabel != NULL) {
|
||||||
return -1;
|
if (STREQ(relabel, "yes")) {
|
||||||
}
|
def->seclabels[i]->norelabel = false;
|
||||||
|
} else if (STREQ(relabel, "no")) {
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/@relabel)",
|
def->seclabels[i]->norelabel = true;
|
||||||
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 {
|
} else {
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
_("invalid security relabel value %s"), p);
|
_("invalid security relabel value %s"),
|
||||||
VIR_FREE(p);
|
relabel);
|
||||||
VIR_FREE(*def);
|
VIR_FREE(relabel);
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
VIR_FREE(p);
|
VIR_FREE(relabel);
|
||||||
} else {
|
} else {
|
||||||
(*def)->norelabel = false;
|
def->seclabels[i]->norelabel = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = virXPathStringLimit("string(./seclabel[1]/label[1])",
|
ctxt->node = list[i];
|
||||||
|
label = virXPathStringLimit("string(./label)",
|
||||||
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
|
||||||
(*def)->label = p;
|
def->seclabels[i]->label = label;
|
||||||
|
|
||||||
if ((*def)->label && (*def)->norelabel) {
|
if (label && def->seclabels[i]->norelabel) {
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
_("Cannot specify a label if relabelling is turned off"));
|
_("Cannot specify a label if relabelling is "
|
||||||
VIR_FREE((*def)->label);
|
"turned off. model=%s"),
|
||||||
VIR_FREE(*def);
|
def->seclabels[i]->model);
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
VIR_FREE(list);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
virSecurityDeviceLabelDefFree(def->seclabels[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(def->seclabels);
|
||||||
|
VIR_FREE(list);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3246,7 +3334,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
xmlNodePtr node,
|
xmlNodePtr node,
|
||||||
xmlXPathContextPtr ctxt,
|
xmlXPathContextPtr ctxt,
|
||||||
virBitmapPtr bootMap,
|
virBitmapPtr bootMap,
|
||||||
virSecurityLabelDefPtr vmSeclabel,
|
virSecurityLabelDefPtr* vmSeclabels,
|
||||||
|
int nvmSeclabels,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
virDomainDiskDefPtr def;
|
virDomainDiskDefPtr def;
|
||||||
@ -3584,15 +3673,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
if (sourceNode) {
|
if (sourceNode) {
|
||||||
xmlNodePtr saved_node = ctxt->node;
|
xmlNodePtr saved_node = ctxt->node;
|
||||||
ctxt->node = sourceNode;
|
ctxt->node = sourceNode;
|
||||||
if ((VIR_ALLOC(def->seclabels) < 0)) {
|
if (virSecurityDeviceLabelDefParseXML(def, vmSeclabels,
|
||||||
virReportOOMError();
|
nvmSeclabels,
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (virSecurityDeviceLabelDefParseXML(&def->seclabels[0],
|
|
||||||
vmSeclabel,
|
|
||||||
ctxt) < 0)
|
ctxt) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
def->nseclabels = 1;
|
|
||||||
ctxt->node = saved_node;
|
ctxt->node = saved_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7064,18 +7148,11 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!def->seclabels) {
|
|
||||||
if ((VIR_ALLOC(def->seclabels) < 0) ||
|
|
||||||
(VIR_ALLOC(def->seclabels[0])) < 0 ) {
|
|
||||||
virReportOOMError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
||||||
dev->type = VIR_DOMAIN_DEVICE_DISK;
|
dev->type = VIR_DOMAIN_DEVICE_DISK;
|
||||||
if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, ctxt,
|
if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, ctxt,
|
||||||
NULL, def->seclabels[0],
|
NULL, def->seclabels,
|
||||||
|
def->nseclabels,
|
||||||
flags)))
|
flags)))
|
||||||
goto error;
|
goto error;
|
||||||
} else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
|
} else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
|
||||||
@ -8014,13 +8091,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
|
|
||||||
/* analysis of security label, done early even though we format it
|
/* analysis of security label, done early even though we format it
|
||||||
* late, so devices can refer to this for defaults */
|
* late, so devices can refer to this for defaults */
|
||||||
if ((VIR_ALLOC(def->seclabels) < 0) ||
|
if (virSecurityLabelDefsParseXML(def, ctxt, flags) == -1)
|
||||||
(VIR_ALLOC(def->seclabels[0]) < 0)) {
|
|
||||||
virReportOOMError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
def->nseclabels = 1;
|
|
||||||
if (virSecurityLabelDefParseXML(def->seclabels[0], ctxt, flags) == -1)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Extract domain memory */
|
/* Extract domain memory */
|
||||||
@ -8620,7 +8691,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
nodes[i],
|
nodes[i],
|
||||||
ctxt,
|
ctxt,
|
||||||
bootMap,
|
bootMap,
|
||||||
def->seclabels[0],
|
def->seclabels,
|
||||||
|
def->nseclabels,
|
||||||
flags);
|
flags);
|
||||||
if (!disk)
|
if (!disk)
|
||||||
goto error;
|
goto error;
|
||||||
@ -10975,13 +11047,14 @@ virSecurityLabelDefFormat(virBufferPtr buf, virSecurityLabelDefPtr def)
|
|||||||
virBufferAsprintf(buf, "<seclabel type='%s'",
|
virBufferAsprintf(buf, "<seclabel type='%s'",
|
||||||
sectype);
|
sectype);
|
||||||
|
|
||||||
|
if (def->model)
|
||||||
|
virBufferEscapeString(buf, " model='%s'", def->model);
|
||||||
|
|
||||||
if (def->type == VIR_DOMAIN_SECLABEL_NONE) {
|
if (def->type == VIR_DOMAIN_SECLABEL_NONE) {
|
||||||
virBufferAddLit(buf, "/>\n");
|
virBufferAddLit(buf, "/>\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virBufferEscapeString(buf, " model='%s'", def->model);
|
|
||||||
|
|
||||||
virBufferAsprintf(buf, " relabel='%s'",
|
virBufferAsprintf(buf, " relabel='%s'",
|
||||||
def->norelabel ? "no" : "yes");
|
def->norelabel ? "no" : "yes");
|
||||||
|
|
||||||
@ -11007,8 +11080,8 @@ static void
|
|||||||
virSecurityDeviceLabelDefFormat(virBufferPtr buf,
|
virSecurityDeviceLabelDefFormat(virBufferPtr buf,
|
||||||
virSecurityDeviceLabelDefPtr def)
|
virSecurityDeviceLabelDefPtr def)
|
||||||
{
|
{
|
||||||
virBufferAsprintf(buf, "<seclabel relabel='%s'",
|
virBufferAsprintf(buf, "<seclabel model='%s' relabel='%s'",
|
||||||
def->norelabel ? "no" : "yes");
|
def->model, def->norelabel ? "no" : "yes");
|
||||||
if (def->label) {
|
if (def->label) {
|
||||||
virBufferAddLit(buf, ">\n");
|
virBufferAddLit(buf, ">\n");
|
||||||
virBufferEscapeString(buf, " <label>%s</label>\n",
|
virBufferEscapeString(buf, " <label>%s</label>\n",
|
||||||
@ -11053,6 +11126,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
const char *copy_on_read = virDomainVirtioEventIdxTypeToString(def->copy_on_read);
|
const char *copy_on_read = virDomainVirtioEventIdxTypeToString(def->copy_on_read);
|
||||||
const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
|
const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
|
||||||
|
|
||||||
|
int n;
|
||||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
@ -11148,10 +11222,11 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
if (def->startupPolicy)
|
if (def->startupPolicy)
|
||||||
virBufferEscapeString(buf, " startupPolicy='%s'",
|
virBufferEscapeString(buf, " startupPolicy='%s'",
|
||||||
startupPolicy);
|
startupPolicy);
|
||||||
if (def->seclabels && def->seclabels[0]) {
|
if (def->nseclabels) {
|
||||||
virBufferAddLit(buf, ">\n");
|
virBufferAddLit(buf, ">\n");
|
||||||
virBufferAdjustIndent(buf, 8);
|
virBufferAdjustIndent(buf, 8);
|
||||||
virSecurityDeviceLabelDefFormat(buf, def->seclabels[0]);
|
for (n = 0; n < def->nseclabels; n++)
|
||||||
|
virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
|
||||||
virBufferAdjustIndent(buf, -8);
|
virBufferAdjustIndent(buf, -8);
|
||||||
virBufferAddLit(buf, " </source>\n");
|
virBufferAddLit(buf, " </source>\n");
|
||||||
} else {
|
} else {
|
||||||
@ -11161,10 +11236,11 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
case VIR_DOMAIN_DISK_TYPE_BLOCK:
|
case VIR_DOMAIN_DISK_TYPE_BLOCK:
|
||||||
virBufferEscapeString(buf, " <source dev='%s'",
|
virBufferEscapeString(buf, " <source dev='%s'",
|
||||||
def->src);
|
def->src);
|
||||||
if (def->seclabels && def->seclabels[0]) {
|
if (def->nseclabels) {
|
||||||
virBufferAddLit(buf, ">\n");
|
virBufferAddLit(buf, ">\n");
|
||||||
virBufferAdjustIndent(buf, 8);
|
virBufferAdjustIndent(buf, 8);
|
||||||
virSecurityDeviceLabelDefFormat(buf, def->seclabels[0]);
|
for (n = 0; n < def->nseclabels; n++)
|
||||||
|
virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
|
||||||
virBufferAdjustIndent(buf, -8);
|
virBufferAdjustIndent(buf, -8);
|
||||||
virBufferAddLit(buf, " </source>\n");
|
virBufferAddLit(buf, " </source>\n");
|
||||||
} else {
|
} else {
|
||||||
@ -13158,11 +13234,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|||||||
|
|
||||||
virBufferAddLit(buf, " </devices>\n");
|
virBufferAddLit(buf, " </devices>\n");
|
||||||
|
|
||||||
if (def->nseclabels && def->seclabels) {
|
|
||||||
virBufferAdjustIndent(buf, 2);
|
virBufferAdjustIndent(buf, 2);
|
||||||
virSecurityLabelDefFormat(buf, def->seclabels[0]);
|
for (n = 0; n < def->nseclabels; n++)
|
||||||
|
virSecurityLabelDefFormat(buf, def->seclabels[n]);
|
||||||
virBufferAdjustIndent(buf, -2);
|
virBufferAdjustIndent(buf, -2);
|
||||||
}
|
|
||||||
|
|
||||||
if (def->namespaceData && def->ns.format) {
|
if (def->namespaceData && def->ns.format) {
|
||||||
if ((def->ns.format)(buf, def->namespaceData) < 0)
|
if ((def->ns.format)(buf, def->namespaceData) < 0)
|
||||||
@ -15529,3 +15604,65 @@ cleanup:
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virSecurityLabelDefPtr
|
||||||
|
virDomainDefGetSecurityLabelDef(virDomainDefPtr def, const char *model)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (def == NULL || model == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < def->nseclabels; i++) {
|
||||||
|
if (def->seclabels[i]->model == NULL)
|
||||||
|
continue;
|
||||||
|
if (STREQ(def->seclabels[i]->model, model))
|
||||||
|
return def->seclabels[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return virDomainDefAddSecurityLabelDef(def, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
virSecurityDeviceLabelDefPtr
|
||||||
|
virDomainDiskDefGetSecurityLabelDef(virDomainDiskDefPtr def, const char *model)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (def == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < def->nseclabels; i++) {
|
||||||
|
if (STREQ(def->seclabels[i]->model, model))
|
||||||
|
return def->seclabels[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virSecurityLabelDefPtr
|
||||||
|
virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char *model)
|
||||||
|
{
|
||||||
|
virSecurityLabelDefPtr seclabel = NULL;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(seclabel) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model) {
|
||||||
|
seclabel->model = strdup(model);
|
||||||
|
if (seclabel->model == NULL) {
|
||||||
|
virReportOOMError();
|
||||||
|
virSecurityLabelDefFree(seclabel);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_EXPAND_N(def->seclabels, def->nseclabels, 1) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
virSecurityLabelDefFree(seclabel);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
def->seclabels[def->nseclabels - 1] = seclabel;
|
||||||
|
|
||||||
|
return seclabel;
|
||||||
|
}
|
||||||
|
@ -2143,6 +2143,15 @@ virDomainState
|
|||||||
virDomainObjGetState(virDomainObjPtr obj, int *reason)
|
virDomainObjGetState(virDomainObjPtr obj, int *reason)
|
||||||
ATTRIBUTE_NONNULL(1);
|
ATTRIBUTE_NONNULL(1);
|
||||||
|
|
||||||
|
virSecurityLabelDefPtr
|
||||||
|
virDomainDefGetSecurityLabelDef(virDomainDefPtr def, const char *model);
|
||||||
|
|
||||||
|
virSecurityDeviceLabelDefPtr
|
||||||
|
virDomainDiskDefGetSecurityLabelDef(virDomainDiskDefPtr def, const char *model);
|
||||||
|
|
||||||
|
virSecurityLabelDefPtr
|
||||||
|
virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char *model);
|
||||||
|
|
||||||
typedef const char* (*virLifecycleToStringFunc)(int type);
|
typedef const char* (*virLifecycleToStringFunc)(int type);
|
||||||
typedef int (*virLifecycleFromStringFunc)(const char *type);
|
typedef int (*virLifecycleFromStringFunc)(const char *type);
|
||||||
|
|
||||||
|
@ -300,6 +300,9 @@ virDomainDefCompatibleDevice;
|
|||||||
virDomainDefFormat;
|
virDomainDefFormat;
|
||||||
virDomainDefFormatInternal;
|
virDomainDefFormatInternal;
|
||||||
virDomainDefFree;
|
virDomainDefFree;
|
||||||
|
virDomainDefGetSecurityLabelDef;
|
||||||
|
virDomainDiskDefGetSecurityLabelDef;
|
||||||
|
virDomainDefAddSecurityLabelDef;
|
||||||
virDomainDefParseFile;
|
virDomainDefParseFile;
|
||||||
virDomainDefParseNode;
|
virDomainDefParseNode;
|
||||||
virDomainDefParseString;
|
virDomainDefParseString;
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
<emulator>/usr/bin/qemu</emulator>
|
<emulator>/usr/bin/qemu</emulator>
|
||||||
<disk type='block' device='disk'>
|
<disk type='block' device='disk'>
|
||||||
<source dev='/dev/HostVG/QEMUGuest1'>
|
<source dev='/dev/HostVG/QEMUGuest1'>
|
||||||
<seclabel relabel='no'/>
|
<seclabel model='selinux' relabel='no'/>
|
||||||
</source>
|
</source>
|
||||||
<target dev='hda' bus='ide'/>
|
<target dev='hda' bus='ide'/>
|
||||||
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||||
</disk>
|
</disk>
|
||||||
<disk type='block' device='disk'>
|
<disk type='block' device='disk'>
|
||||||
<source dev='/dev/HostVG/QEMUGuest2'>
|
<source dev='/dev/HostVG/QEMUGuest2'>
|
||||||
<seclabel relabel='yes'>
|
<seclabel model='selinux' relabel='yes'>
|
||||||
<label>system_u:system_r:public_content_t:s0</label>
|
<label>system_u:system_r:public_content_t:s0</label>
|
||||||
</seclabel>
|
</seclabel>
|
||||||
</source>
|
</source>
|
||||||
|
@ -22,5 +22,5 @@
|
|||||||
<controller type='ide' index='0'/>
|
<controller type='ide' index='0'/>
|
||||||
<memballoon model='virtio'/>
|
<memballoon model='virtio'/>
|
||||||
</devices>
|
</devices>
|
||||||
<seclabel type='dynamic' relabel='yes'/>
|
<seclabel model='selinux' type='dynamic' relabel='yes'/>
|
||||||
</domain>
|
</domain>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user