]> xenbits.xensource.com Git - libvirt.git/commitdiff
Allow a base label to be specified in dynamic labelling mode
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 23 Jun 2011 14:48:48 +0000 (15:48 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 4 Jul 2011 10:17:19 +0000 (11:17 +0100)
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
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_process.c
src/security/security_apparmor.c
src/security/security_selinux.c

index 891662df7ca6551d8029b469c4d0a29454671015..ab5a56b218e597ba8f2b56ea7599827b0a3a10bf 100644 (file)
@@ -67,6 +67,9 @@
       <element name="imagelabel">
         <text/>
       </element>
+      <element name="baselabel">
+        <text/>
+      </element>
     </element>
   </define>
   <define name="hvs">
index f9bf51e3c7210443afdb34fd03650f4bf2f16b76..1da242fd16290e7c299b7fe6fd0ee17acdb01d5f 100644 (file)
@@ -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");
         }
     }
index e81977c61a341bb0f51eefd50483f63dfc446532..76b9ca7395d808636054022d0b72a7a400acda95 100644 (file)
@@ -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;
 };
 
index 88a31a3e5453790d500a7b89ec1c7798a8fdbee6..69788dfa1c416d33be659774b728e9c303cc6801 100644 (file)
@@ -2883,7 +2883,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);
     }
index 6795184c4c176d57999c755493a79f268afc8da5..bbdcbf023c500ff14a16a68ccb3a4511cb4af9df 100644 (file)
@@ -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,
index a022daa778aa4610520ea522b544e30f63e8b4a5..913c7a622d535b7c9f987ecda85db05a3bb3ebff 100644 (file)
@@ -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;