[libvirt] [PATCH 1/3] Allow a base label to be specified in dynamic labelling mode

Daniel P. Berrange berrange at redhat.com
Mon Jun 27 12:20:36 UTC 2011


Normally the dynamic labelling mode will always use a base
label of 'svirt_t' for VMs. Introduce a <baselabel> field
in the <seclabel> XML to allow this base label to be changed

eg

   <seclabel type='dynamic' model='selinux'>
     <baselabel>system_u:object_r:virt_t:s0</baselabel>
   </seclabel>

* docs/schemas/domain.rng: Add <baselabel>
* src/conf/domain_conf.c, src/conf/domain_conf.h: Parsing
  of base label
* src/qemu/qemu_process.c: Don't reset 'model' attribute if
  a base label is specified
* src/security/security_apparmor.c: Refuse to support base label
* src/security/security_selinux.c: Use 'baselabel' when generating
  label, if available
---
 docs/schemas/domain.rng          |    3 ++
 src/conf/domain_conf.c           |   56 ++++++++++++++++++++++++++-----------
 src/conf/domain_conf.h           |    1 +
 src/qemu/qemu_process.c          |    3 +-
 src/security/security_apparmor.c |    6 ++++
 src/security/security_selinux.c  |   29 ++++++++++++++++---
 6 files changed, 75 insertions(+), 23 deletions(-)

diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 891662d..ab5a56b 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -67,6 +67,9 @@
       <element name="imagelabel">
         <text/>
       </element>
+      <element name="baselabel">
+        <text/>
+      </element>
     </element>
   </define>
   <define name="hvs">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3d290fb..cc318da 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -966,6 +966,7 @@ void virSecurityLabelDefFree(virDomainDefPtr def)
     VIR_FREE(def->seclabel.model);
     VIR_FREE(def->seclabel.label);
     VIR_FREE(def->seclabel.imagelabel);
+    VIR_FREE(def->seclabel.baselabel);
 }
 
 static void
@@ -5072,20 +5073,11 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def,
         goto error;
     }
 
-    /* Only parse details, if using static labels, or
+    /* Only parse label, if using static labels, or
      * if the 'live' VM XML is requested
      */
     if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
         !(flags & VIR_DOMAIN_XML_INACTIVE)) {
-        p = virXPathStringLimit("string(./seclabel/@model)",
-                                VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
-        if (p == NULL) {
-            virDomainReportError(VIR_ERR_XML_ERROR,
-                                 "%s", _("missing security model"));
-            goto error;
-        }
-        def->seclabel.model = p;
-
         p = virXPathStringLimit("string(./seclabel/label[1])",
                                 VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
         if (p == NULL) {
@@ -5110,6 +5102,30 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def,
         def->seclabel.imagelabel = p;
     }
 
+    /* Only parse baselabel, for dynamic label */
+    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+        p = virXPathStringLimit("string(./seclabel/baselabel[1])",
+                                VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
+        if (p != NULL)
+            def->seclabel.baselabel = p;
+    }
+
+    /* Only parse model, if static labelling, or a base
+     * label is set, or doing active XML
+     */
+    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
+        def->seclabel.baselabel ||
+        !(flags & VIR_DOMAIN_XML_INACTIVE)) {
+        p = virXPathStringLimit("string(./seclabel/@model)",
+                                VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
+        if (p == NULL) {
+            virDomainReportError(VIR_ERR_XML_ERROR,
+                                 "%s", _("missing security model"));
+            goto error;
+        }
+        def->seclabel.model = p;
+    }
+
     return 0;
 
 error:
@@ -9844,20 +9860,26 @@ char *virDomainDefFormat(virDomainDefPtr def,
         const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type);
         if (!sectype)
             goto cleanup;
-        if (!def->seclabel.label ||
-            (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
-             (flags & VIR_DOMAIN_XML_INACTIVE))) {
+
+        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+            !def->seclabel.baselabel &&
+            (flags & VIR_DOMAIN_XML_INACTIVE)) {
             virBufferAsprintf(&buf, "  <seclabel type='%s' model='%s'/>\n",
                               sectype, def->seclabel.model);
         } else {
             virBufferAsprintf(&buf, "  <seclabel type='%s' model='%s'>\n",
-                                  sectype, def->seclabel.model);
-            virBufferEscapeString(&buf, "    <label>%s</label>\n",
-                                  def->seclabel.label);
+                              sectype, def->seclabel.model);
+            if (def->seclabel.label)
+                virBufferEscapeString(&buf, "    <label>%s</label>\n",
+                                      def->seclabel.label);
             if (def->seclabel.imagelabel &&
-                def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
+                (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC))
                 virBufferEscapeString(&buf, "    <imagelabel>%s</imagelabel>\n",
                                       def->seclabel.imagelabel);
+            if (def->seclabel.baselabel &&
+                (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC))
+                virBufferEscapeString(&buf, "    <baselabel>%s</baselabel>\n",
+                                      def->seclabel.baselabel);
             virBufferAddLit(&buf, "  </seclabel>\n");
         }
     }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index aa25e36..17c2584 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -958,6 +958,7 @@ struct _virSecurityLabelDef {
     char *model;        /* name of security model */
     char *label;        /* security label string */
     char *imagelabel;   /* security image label string */
+    char *baselabel;    /* base name of label string */
     int type;
 };
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index bb83be0..1a404ff 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2908,7 +2908,8 @@ void qemuProcessStop(struct qemud_driver *driver,
 
     /* Clear out dynamically assigned labels */
     if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
-        VIR_FREE(vm->def->seclabel.model);
+        if (!vm->def->seclabel.baselabel)
+            VIR_FREE(vm->def->seclabel.model);
         VIR_FREE(vm->def->seclabel.label);
         VIR_FREE(vm->def->seclabel.imagelabel);
     }
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index aebf44e..b6ce5b7 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -398,6 +398,12 @@ AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
     if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
 
+    if (vm->def->seclabel.baselabel) {
+        virSecurityReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               "%s", _("Cannot set a base label with AppArmour"));
+        return rc;
+    }
+
     if ((vm->def->seclabel.label) ||
         (vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 0ce999f..736cd7f 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -173,14 +173,29 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
     if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
         return 0;
 
+    if ((vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
+        !vm->def->seclabel.baselabel &&
+        vm->def->seclabel.model) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("security model already defined for VM"));
+        return rc;
+    }
+
     if (vm->def->seclabel.label ||
-        vm->def->seclabel.model ||
         vm->def->seclabel.imagelabel) {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("security label already defined for VM"));
         return rc;
     }
 
+    if (vm->def->seclabel.model &&
+        STRNEQ(vm->def->seclabel.model, SECURITY_SELINUX_NAME)) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("security label model %s is not supported with selinux"),
+                               vm->def->seclabel.model);
+        return rc;
+    }
+
     do {
         c1 = virRandom(1024);
         c2 = virRandom(1024);
@@ -195,7 +210,10 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
         }
     } while(mcsAdd(mcs) == -1);
 
-    vm->def->seclabel.label = SELinuxGenNewContext(default_domain_context, mcs);
+    vm->def->seclabel.label =
+        SELinuxGenNewContext(vm->def->seclabel.baselabel ?
+                             vm->def->seclabel.baselabel :
+                             default_domain_context, mcs);
     if (! vm->def->seclabel.label)  {
         virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                _("cannot generate selinux context for %s"), mcs);
@@ -207,8 +225,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                                _("cannot generate selinux context for %s"), mcs);
         goto err;
     }
-    vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME);
-    if (!vm->def->seclabel.model) {
+    if (!vm->def->seclabel.model &&
+        !(vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) {
         virReportOOMError();
         goto err;
     }
@@ -219,7 +237,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
 err:
     VIR_FREE(vm->def->seclabel.label);
     VIR_FREE(vm->def->seclabel.imagelabel);
-    VIR_FREE(vm->def->seclabel.model);
+    if (!vm->def->seclabel.baselabel)
+        VIR_FREE(vm->def->seclabel.model);
 done:
     VIR_FREE(scontext);
     return rc;
-- 
1.7.4.4




More information about the libvir-list mailing list