c401cc
From f121962023596527c9ec798950044b723ca4857e Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <f121962023596527c9ec798950044b723ca4857e.1385135432.git.jdenemar@redhat.com>
c401cc
From: Michal Privoznik <mprivozn@redhat.com>
c401cc
Date: Mon, 11 Nov 2013 17:12:59 +0100
c401cc
Subject: [PATCH] virSecurityLabelDefParseXML: Don't parse label on
c401cc
 model='none'
c401cc
c401cc
RHEL-7.0: https://bugzilla.redhat.com/show_bug.cgi?id=1028962
c401cc
RHEL-6.6: https://bugzilla.redhat.com/show_bug.cgi?id=1027096
c401cc
c401cc
If there's the following snippet in the domain XML, the domain will be
c401cc
lost upon the daemon restart (if the domain is started prior restart):
c401cc
c401cc
    <seclabel type='dynamic' relabel='yes'/>
c401cc
c401cc
The problem is, the 'label', 'imagelabel' and 'baselabel' are parsed
c401cc
whenever the VIR_DOMAIN_XML_INACTIVE is *not* present or the label is
c401cc
static. The latter is not our case, obviously. So, when libvirtd starts
c401cc
up, it finds domain state xml and parse it. During parsing, many XML
c401cc
flags are enabled but VIR_DOMAIN_XML_INACTIVE. Hence, our parser tries
c401cc
to extract 'label', 'imagelabel' and 'baselabel' from the XML which
c401cc
fails for model='none'. Err, this model - even though not specified in
c401cc
XML - can be taken from qemu wide config file: /etc/libvirtd/qemu.conf.
c401cc
c401cc
However, in order to know we are dealing with model='none' the code in
c401cc
question must be moved forward a bit. Then a new check must be
c401cc
introduced. This is what the first two chunks are doing.
c401cc
c401cc
But this alone is not sufficient. The domain state XML won't contain the
c401cc
model attribute without slight modification. The model should be
c401cc
inserted into the XML even if equal to 'none' and the state XML is being
c401cc
generated - what if the origin (the @security_driver variable in
c401cc
qemu.conf) changes during libvirtd restarts?
c401cc
c401cc
At the end, a test to catch this scenario is introduced.
c401cc
c401cc
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
c401cc
(cherry picked from commit 9fb3f9571db4bd20b8287a160e9b2680f23dde45)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/conf/domain_conf.c                             | 26 +++++++++++++-------
c401cc
 .../qemuxml2argv-seclabel-dynamic-relabel.args     |  6 +++++
c401cc
 .../qemuxml2argv-seclabel-dynamic-relabel.xml      | 28 ++++++++++++++++++++++
c401cc
 tests/qemuxml2argvtest.c                           |  1 +
c401cc
 tests/qemuxml2xmltest.c                            |  1 +
c401cc
 5 files changed, 54 insertions(+), 8 deletions(-)
c401cc
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.args
c401cc
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.xml
c401cc
c401cc
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
c401cc
index 57a82b6..8307fee 100644
c401cc
--- a/src/conf/domain_conf.c
c401cc
+++ b/src/conf/domain_conf.c
c401cc
@@ -4350,6 +4350,17 @@ virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,
c401cc
             def->norelabel = false;
c401cc
     }
c401cc
 
c401cc
+    /* Always parse model */
c401cc
+    p = virXPathStringLimit("string(./@model)",
c401cc
+                            VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
c401cc
+    def->model = p;
c401cc
+
c401cc
+    /* For the model 'none' none of the following labels is going to be
c401cc
+     * present. Hence, return now. */
c401cc
+
c401cc
+    if (STREQ_NULLABLE(def->model, "none"))
c401cc
+        return def;
c401cc
+
c401cc
     /* Only parse label, if using static labels, or
c401cc
      * if the 'live' VM XML is requested
c401cc
      */
c401cc
@@ -4388,11 +4399,6 @@ virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,
c401cc
         def->baselabel = p;
c401cc
     }
c401cc
 
c401cc
-    /* Always parse model */
c401cc
-    p = virXPathStringLimit("string(./@model)",
c401cc
-                            VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
c401cc
-    def->model = p;
c401cc
-
c401cc
     return def;
c401cc
 
c401cc
 error:
c401cc
@@ -14092,7 +14098,9 @@ virDomainEventActionDefFormat(virBufferPtr buf,
c401cc
 
c401cc
 
c401cc
 static void
c401cc
-virSecurityLabelDefFormat(virBufferPtr buf, virSecurityLabelDefPtr def)
c401cc
+virSecurityLabelDefFormat(virBufferPtr buf,
c401cc
+                          virSecurityLabelDefPtr def,
c401cc
+                          unsigned flags)
c401cc
 {
c401cc
     const char *sectype = virDomainSeclabelTypeToString(def->type);
c401cc
 
c401cc
@@ -14111,7 +14119,9 @@ virSecurityLabelDefFormat(virBufferPtr buf, virSecurityLabelDefPtr def)
c401cc
     virBufferAsprintf(buf, "
c401cc
                       sectype);
c401cc
 
c401cc
-    if (def->model && STRNEQ(def->model, "none"))
c401cc
+    /* When generating state XML do include the model */
c401cc
+    if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS ||
c401cc
+        STRNEQ_NULLABLE(def->model, "none"))
c401cc
         virBufferEscapeString(buf, " model='%s'", def->model);
c401cc
 
c401cc
     if (def->type == VIR_DOMAIN_SECLABEL_NONE) {
c401cc
@@ -17006,7 +17016,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
c401cc
 
c401cc
     virBufferAdjustIndent(buf, 2);
c401cc
     for (n = 0; n < def->nseclabels; n++)
c401cc
-        virSecurityLabelDefFormat(buf, def->seclabels[n]);
c401cc
+        virSecurityLabelDefFormat(buf, def->seclabels[n], flags);
c401cc
     virBufferAdjustIndent(buf, -2);
c401cc
 
c401cc
     if (def->namespaceData && def->ns.format) {
c401cc
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.args b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.args
c401cc
new file mode 100644
c401cc
index 0000000..5bbde17
c401cc
--- /dev/null
c401cc
+++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.args
c401cc
@@ -0,0 +1,6 @@
c401cc
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
c401cc
+/usr/bin/qemu \
c401cc
+-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \
c401cc
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
c401cc
+-hda /dev/HostVG/QEMUGuest1 -net none -serial \
c401cc
+none -parallel none
c401cc
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.xml
c401cc
new file mode 100644
c401cc
index 0000000..cb74239
c401cc
--- /dev/null
c401cc
+++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-relabel.xml
c401cc
@@ -0,0 +1,28 @@
c401cc
+<domain type='qemu'>
c401cc
+  <name>QEMUGuest1</name>
c401cc
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
c401cc
+  <memory unit='KiB'>219100</memory>
c401cc
+  <currentMemory unit='KiB'>219100</currentMemory>
c401cc
+  <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
c401cc
+  <os>
c401cc
+    <type arch='i686' machine='pc'>hvm</type>
c401cc
+    <boot dev='hd'/>
c401cc
+  </os>
c401cc
+  <clock offset='utc'/>
c401cc
+  <on_poweroff>destroy</on_poweroff>
c401cc
+  <on_reboot>restart</on_reboot>
c401cc
+  <on_crash>destroy</on_crash>
c401cc
+  <devices>
c401cc
+    <emulator>/usr/bin/qemu</emulator>
c401cc
+    <disk type='block' device='disk'>
c401cc
+      <source dev='/dev/HostVG/QEMUGuest1'/>
c401cc
+      <target dev='hda' bus='ide'/>
c401cc
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
c401cc
+    </disk>
c401cc
+    <controller type='usb' index='0'/>
c401cc
+    <controller type='ide' index='0'/>
c401cc
+    <controller type='pci' index='0' model='pci-root'/>
c401cc
+    <memballoon model='virtio'/>
c401cc
+  </devices>
c401cc
+  <seclabel type='dynamic' relabel='yes'/>
c401cc
+</domain>
c401cc
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
c401cc
index 2f05727..cfaee71 100644
c401cc
--- a/tests/qemuxml2argvtest.c
c401cc
+++ b/tests/qemuxml2argvtest.c
c401cc
@@ -939,6 +939,7 @@ mymain(void)
c401cc
     DO_TEST("seclabel-dynamic-baselabel", QEMU_CAPS_NAME);
c401cc
     DO_TEST("seclabel-dynamic-override", QEMU_CAPS_NAME);
c401cc
     DO_TEST("seclabel-dynamic-labelskip", QEMU_CAPS_NAME);
c401cc
+    DO_TEST("seclabel-dynamic-relabel", QEMU_CAPS_NAME);
c401cc
     DO_TEST("seclabel-static", QEMU_CAPS_NAME);
c401cc
     DO_TEST("seclabel-static-relabel", QEMU_CAPS_NAME);
c401cc
     DO_TEST("seclabel-static-labelskip", QEMU_CAPS_NAME);
c401cc
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
c401cc
index 5a47ef8..6b984ad 100644
c401cc
--- a/tests/qemuxml2xmltest.c
c401cc
+++ b/tests/qemuxml2xmltest.c
c401cc
@@ -260,6 +260,7 @@ mymain(void)
c401cc
     DO_TEST_FULL("seclabel-dynamic-baselabel", false, WHEN_INACTIVE);
c401cc
     DO_TEST_FULL("seclabel-dynamic-override", false, WHEN_INACTIVE);
c401cc
     DO_TEST_FULL("seclabel-dynamic-labelskip", true, WHEN_INACTIVE);
c401cc
+    DO_TEST_FULL("seclabel-dynamic-relabel", false, WHEN_INACTIVE);
c401cc
     DO_TEST("seclabel-static");
c401cc
     DO_TEST_FULL("seclabel-static-labelskip", false, WHEN_ACTIVE);
c401cc
     DO_TEST("seclabel-none");
c401cc
-- 
c401cc
1.8.4.4
c401cc