diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 12a756c2817573c9ec821733cfcf9e7e84a16738..ec011dd414ca9ed8b0e2f9a64b19340bfeb573b9 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5029,7 +5029,11 @@ qemu-kvm -net nic,model=? /dev/null
a seclabel
element is attached to a specific path
rather than the top-level domain assignment, only the
attribute relabel
or the
- sub-element label
are supported.
+ sub-element label
are supported. Additionally,
+ since 1.1.2 , an output-only
+ element labelskip
will be present for active
+ domains on disks where labeling was skipped due to the image
+ being on a file system that lacks security labeling.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index ac807e6caf0f3ea67ef990937d9d048dd386e6c3..dfcd61cdd25aef86f6bb3b0dd320063e940e1d16 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -152,34 +152,35 @@
+ relabel=no or a must be present on input;
+ output also can include labelskip=yes. -->
+
+
+
+
+
-
-
-
-
-
no
-
-
-
-
-
+
+ yes
+
+
+
yes
-
+
-
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 12b68eadf1fc109b8376d51adc4ee1f75ee9246f..ea49d2cda38af3ddde7fae8eaaa187cd77fd5d52 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4484,7 +4484,8 @@ static int
virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn,
size_t *nseclabels_rtn,
virSecurityLabelDefPtr *vmSeclabels,
- int nvmSeclabels, xmlXPathContextPtr ctxt)
+ int nvmSeclabels, xmlXPathContextPtr ctxt,
+ unsigned int flags)
{
virSecurityDeviceLabelDefPtr *seclabels;
size_t nseclabels = 0;
@@ -4492,7 +4493,7 @@ virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn,
size_t i, j;
xmlNodePtr *list = NULL;
virSecurityLabelDefPtr vmDef = NULL;
- char *model, *relabel, *label;
+ char *model, *relabel, *label, *labelskip;
if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) < 0)
goto error;
@@ -4547,6 +4548,13 @@ virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn,
seclabels[i]->norelabel = false;
}
+ /* labelskip is only parsed on live images */
+ labelskip = virXMLPropString(list[i], "labelskip");
+ seclabels[i]->labelskip = false;
+ if (labelskip && !(flags & VIR_DOMAIN_XML_INACTIVE))
+ seclabels[i]->labelskip = STREQ(labelskip, "yes");
+ VIR_FREE(labelskip);
+
ctxt->node = list[i];
label = virXPathStringLimit("string(./label)",
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
@@ -5208,7 +5216,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
&def->nseclabels,
vmSeclabels,
nvmSeclabels,
- ctxt) < 0)
+ ctxt,
+ flags) < 0)
goto error;
ctxt->node = saved_node;
}
@@ -6884,7 +6893,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
&chr_def->nseclabels,
vmSeclabels,
nvmSeclabels,
- ctxt) < 0) {
+ ctxt,
+ flags) < 0) {
ctxt->node = saved_node;
goto error;
}
@@ -14018,14 +14028,23 @@ virSecurityLabelDefFormat(virBufferPtr buf, virSecurityLabelDefPtr def)
static void
virSecurityDeviceLabelDefFormat(virBufferPtr buf,
- virSecurityDeviceLabelDefPtr def)
+ virSecurityDeviceLabelDefPtr def,
+ unsigned int flags)
{
+ /* For offline output, skip elements that allow labels but have no
+ * label specified (possible if labelskip was ignored on input). */
+ if ((flags & VIR_DOMAIN_XML_INACTIVE) && !def->label && !def->norelabel)
+ return;
+
virBufferAddLit(buf, "model)
virBufferAsprintf(buf, " model='%s'", def->model);
- virBufferAsprintf(buf, " relabel='%s'", def->norelabel ? "no" : "yes");
+ if (def->labelskip)
+ virBufferAddLit(buf, " labelskip='yes'");
+ else
+ virBufferAsprintf(buf, " relabel='%s'", def->norelabel ? "no" : "yes");
if (def->label) {
virBufferAddLit(buf, ">\n");
@@ -14100,7 +14119,8 @@ virDomainDiskBlockIoDefFormat(virBufferPtr buf,
static int
virDomainDiskSourceDefFormat(virBufferPtr buf,
- virDomainDiskDefPtr def)
+ virDomainDiskDefPtr def,
+ unsigned int flags)
{
int n;
const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
@@ -14119,7 +14139,8 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 8);
for (n = 0; n < def->nseclabels; n++)
- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
+ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n],
+ flags);
virBufferAdjustIndent(buf, -8);
virBufferAddLit(buf, " \n");
} else {
@@ -14136,7 +14157,8 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 8);
for (n = 0; n < def->nseclabels; n++)
- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
+ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n],
+ flags);
virBufferAdjustIndent(buf, -8);
virBufferAddLit(buf, " \n");
} else {
@@ -14201,7 +14223,8 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 8);
for (n = 0; n < def->nseclabels; n++)
- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
+ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n],
+ flags);
virBufferAdjustIndent(buf, -8);
virBufferAddLit(buf, " \n");
} else {
@@ -14337,7 +14360,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAddLit(buf, " \n");
}
- if (virDomainDiskSourceDefFormat(buf, def) < 0)
+ if (virDomainDiskSourceDefFormat(buf, def, flags) < 0)
return -1;
virDomainDiskGeometryDefFormat(buf, def);
virDomainDiskBlockIoDefFormat(buf, def);
@@ -15189,7 +15212,7 @@ virDomainChrDefFormat(virBufferPtr buf,
if (def->seclabels && def->nseclabels > 0) {
virBufferAdjustIndent(buf, 2);
for (n = 0; n < def->nseclabels; n++)
- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
+ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n], flags);
virBufferAdjustIndent(buf, -2);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3e118d63d36bd068f2e714755d8af8d93e646849..500a5be9d86149d42b02491a13f48c17b42af7b9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -343,7 +343,8 @@ typedef virSecurityDeviceLabelDef *virSecurityDeviceLabelDefPtr;
struct _virSecurityDeviceLabelDef {
char *model;
char *label; /* image label string */
- bool norelabel;
+ bool norelabel; /* true to skip label attempts */
+ bool labelskip; /* live-only; true if skipping failed label attempt */
};
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index e3dce66a2d7cb1787046e9ae82f431cf8c5ec541..38de06076b017441c36698041d0d0bcdcd609181 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -917,10 +917,10 @@ virSecuritySELinuxSetFileconHelper(const char *path, char *tcon, bool optional)
security_get_boolean_active("virt_use_nfs") != 1) {
msg = _("Setting security context '%s' on '%s' not supported. "
"Consider setting virt_use_nfs");
- if (security_getenforce() == 1)
- VIR_WARN(msg, tcon, path);
- else
- VIR_INFO(msg, tcon, path);
+ if (security_getenforce() == 1)
+ VIR_WARN(msg, tcon, path);
+ else
+ VIR_INFO(msg, tcon, path);
} else {
VIR_INFO("Setting security context '%s' on '%s' not supported",
tcon, path);
@@ -1135,6 +1135,14 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
if (seclabel->norelabel || (disk_seclabel && disk_seclabel->norelabel))
return 0;
+ /* If labelskip is true and there are no backing files, then we
+ * know it is safe to skip the restore. FIXME - backing files should
+ * be tracked in domain XML, at which point labelskip should be a
+ * per-file attribute instead of a disk attribute. */
+ if (disk_seclabel && disk_seclabel->labelskip &&
+ !disk->backingChain)
+ return 0;
+
/* Don't restore labels on readoly/shared disks, because
* other VMs may still be accessing these
* Alternatively we could iterate over all running
@@ -1219,7 +1227,7 @@ virSecuritySELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
disk_seclabel = virDomainDiskDefGenSecurityLabelDef(SECURITY_SELINUX_NAME);
if (!disk_seclabel)
return -1;
- disk_seclabel->norelabel = true;
+ disk_seclabel->labelskip = true;
if (VIR_APPEND_ELEMENT(disk->seclabels, disk->nseclabels,
disk_seclabel) < 0) {
virSecurityDeviceLabelDefFree(disk_seclabel);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args
new file mode 100644
index 0000000000000000000000000000000000000000..892c6b583045714875a39df7bef9abea41b0bafd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
+-hda /dev/HostVG/QEMUGuest1 \
+-net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e3bc7009d924ec4f84ca9f8fe8af9dbc7ece6ade
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml
@@ -0,0 +1,32 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+ system_u:system_r:svirt_custom_t:s0
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args
new file mode 100644
index 0000000000000000000000000000000000000000..892c6b583045714875a39df7bef9abea41b0bafd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
+-hda /dev/HostVG/QEMUGuest1 \
+-net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a7434481db365fc241dbb0701d1ec7ad18d599fc
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+ system_u:system_r:svirt_custom_t:s0:c192,c392
+ system_u:system_r:svirt_custom_t:s0:c192,c392
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 679124e35b52dc754a837dec72a71cf131ad2346..3a3c30415773dc532e388bdb57aab96a3ba38aba 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -923,8 +923,10 @@ mymain(void)
DO_TEST("seclabel-dynamic", QEMU_CAPS_NAME);
DO_TEST("seclabel-dynamic-baselabel", QEMU_CAPS_NAME);
DO_TEST("seclabel-dynamic-override", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-dynamic-labelskip", QEMU_CAPS_NAME);
DO_TEST("seclabel-static", QEMU_CAPS_NAME);
DO_TEST("seclabel-static-relabel", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-static-labelskip", QEMU_CAPS_NAME);
DO_TEST("seclabel-none", QEMU_CAPS_NAME);
DO_TEST("pseries-basic",
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml
new file mode 100644
index 0000000000000000000000000000000000000000..07646913d6c6cfafb5d6059c63c6fc0f78677240
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml
@@ -0,0 +1,31 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+ system_u:system_r:svirt_custom_t:s0
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 5c6730d25ebc54e0dd5cbc4b8f87d106f0646e7f..6eebc685f9d4ce1904afd786f1e9ad01746a10bb 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -30,6 +30,7 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml, bool live)
char *actual = NULL;
int ret = -1;
virDomainDefPtr def = NULL;
+ unsigned int flags = live ? 0 : VIR_DOMAIN_XML_INACTIVE;
if (virtTestLoadFile(inxml, &inXmlData) < 0)
goto fail;
@@ -37,11 +38,10 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml, bool live)
goto fail;
if (!(def = virDomainDefParseString(inXmlData, driver.caps, driver.xmlopt,
- QEMU_EXPECTED_VIRT_TYPES,
- live ? 0 : VIR_DOMAIN_XML_INACTIVE)))
+ QEMU_EXPECTED_VIRT_TYPES, flags)))
goto fail;
- if (!(actual = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE)))
+ if (!(actual = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE | flags)))
goto fail;
if (STRNEQ(outXmlData, actual)) {
@@ -257,7 +257,9 @@ mymain(void)
DO_TEST_FULL("seclabel-dynamic-baselabel", false, WHEN_INACTIVE);
DO_TEST_FULL("seclabel-dynamic-override", false, WHEN_INACTIVE);
+ DO_TEST_FULL("seclabel-dynamic-labelskip", true, WHEN_INACTIVE);
DO_TEST("seclabel-static");
+ DO_TEST_FULL("seclabel-static-labelskip", false, WHEN_ACTIVE);
DO_TEST("seclabel-none");
DO_TEST("numad-static-vcpu-no-numatune");
DO_TEST("disk-scsi-lun-passthrough-sgio");