[libvirt] Re: PATCH: Mark <seclabel> as dynamic generated, or statically pre-defined

Daniel P. Berrange berrange at redhat.com
Tue Mar 3 16:41:13 UTC 2009


On Tue, Mar 03, 2009 at 11:01:34AM -0500, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Daniel P. Berrange wrote:
> > This patch implements the behaviour I was refering to earlier, whereby
> > the domain XML explicitly says whether the security label is a statically
> > pre-defined one, or dynamically generated on VM boot by libvirtd
> > 
> > So when creating a new guest, apps like virt-install have 2 options:
> > 
> >  - Leave out the <seclabel> tag completely
> >     -> If no security driver is active, just works as normal unconfined VM
>
> I want to make sure of terminology.  The VM will be confined, but will
> not be separated.  IE the host machine will be protected from the VM,
> while other VM's will not be.  svirt is concerned with protecting VM's
> from each other.  Normal SELinux protects the Apache server from rogue
> VMs.  If we want to have a truly unconfined vm, we need additional
> policy.  I would suggest permissive mode or a permissive domain.

This was my bad terminolgy. There are two scenarios where a security
driver is not active

 - Admin turned it off in /etc/libvirt/qemu.conf, but SELinux is still
   active on the host in general. The VM will still be confined here,
   but not isolated from each other
 - Admin turned off SELinux for the entire host. The VM will be unconfined


> >     -> If a security driver is active, a dynamic seclabel is generated
> > 
> >       <seclabel type='dynamic' model='selinux'>
> >         <label>system_u:system_r:qemu_t:s0:c424,c719</label>
> >         <imagelabel>system_u:object_r:virt_image_t:s0:c424,c719</imagelabel>
> >       </seclabel>
> > 
> >  - Add an explicit <seclabel> tag with type='static' attribute
> >     -> Security driver uses the defined label & imagelabel
> > 
> >       <seclabel type='static' model='selinux'>
> >         <label>system_u:system_r:qemu_t:s0:c25,c100</label>
> >         <imagelabel>system_u:system_r:virt_image_t:s0:c25,c100</imagelabel>
> >       </seclabel>
> > 
> >
> Not sure imagelabel is required in the second case since, libvirt will
> not change the label.
> 
> This is the biggest difference between static and dynamic, static will
> never run setfilecon, while dynamic runs it at startup and shutdown.
> 
> DYNAMIC:
> 	start
> 	setfilecon(image, imagelabel)
> 	setexeccon(label)
> 	exec()
> 
> 	Finish
> 	ChildExit()
> 	setfilecon(image, DEFAULT_LABEL)
>  	Exit()
> 
> STATIC:
> 	start
> 	setexecon(label)
> 	exec()
> 
> 	Finish:
> 	ChildExit()
> 	Exit()

This new patch implements this logic now. It only parses the <imagelabel>
element from the XML, if parsing the 'live' XML config for a dynamic
label - this is basically just used for libvirt's state file in /var/run,
so it can remember config across libvirtd restarts.

The <imagelabel> is now never used for static labels, and thus no setfilecon()
will take place for them.


Index: src/domain_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.c,v
retrieving revision 1.70
diff -u -p -r1.70 domain_conf.c
--- src/domain_conf.c	3 Mar 2009 09:44:42 -0000	1.70
+++ src/domain_conf.c	3 Mar 2009 16:36:17 -0000
@@ -168,6 +168,10 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN
               "shutoff",
               "crashed")
 
+VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST,
+              "dynamic",
+              "static")
+
 #define virDomainReportError(conn, code, fmt...)                           \
         virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__,        \
                                __FUNCTION__, __LINE__, fmt)
@@ -1847,24 +1851,49 @@ static int virDomainLifecycleParseXML(vi
 static int
 virSecurityLabelDefParseXML(virConnectPtr conn,
                             const virDomainDefPtr def,
-                            xmlXPathContextPtr ctxt)
+                            xmlXPathContextPtr ctxt,
+                            int flags)
 {
     char *p;
 
     if (virXPathNode(conn, "./seclabel", ctxt) == NULL)
         return 0;
 
-    p = virXPathStringLimit(conn, "string(./seclabel/label[1])",
+    p = virXPathStringLimit(conn, "string(./seclabel/@type)",
                             VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
     if (p == NULL)
         goto error;
-    def->seclabel.label = p;
-
-    p = virXPathStringLimit(conn, "string(./seclabel/@model)",
-                            VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
-    if (p == NULL)
+    if ((def->seclabel.type = virDomainSeclabelTypeFromString(p)) < 0)
         goto error;
-    def->seclabel.model = p;
+    VIR_FREE(p);
+
+    /* Only parse details, 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(conn, "string(./seclabel/@model)",
+                                VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
+        if (p == NULL)
+            goto error;
+        def->seclabel.model = p;
+
+        p = virXPathStringLimit(conn, "string(./seclabel/label[1])",
+                                VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
+        if (p == NULL)
+            goto error;
+        def->seclabel.label = p;
+    }
+
+    /* Only parse imagelabel, if requested live XML for dynamic label */
+    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+        !(flags & VIR_DOMAIN_XML_INACTIVE)) {
+        p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])",
+                                VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
+        if (p == NULL)
+            goto error;
+        def->seclabel.imagelabel = p;
+    }
 
     return 0;
 
@@ -2458,7 +2487,7 @@ static virDomainDefPtr virDomainDefParse
     VIR_FREE(nodes);
 
     /* analysis of security label */
-    if (virSecurityLabelDefParseXML(conn, def, ctxt) == -1)
+    if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1)
         goto error;
 
     return def;
@@ -3480,9 +3509,25 @@ char *virDomainDefFormat(virConnectPtr c
     virBufferAddLit(&buf, "  </devices>\n");
 
     if (def->seclabel.model) {
-        virBufferEscapeString(&buf, "  <seclabel model='%s'>\n", def->seclabel.model);
-        virBufferEscapeString(&buf, "    <label>%s</label>\n", def->seclabel.label);
-        virBufferAddLit(&buf, "  </seclabel>\n");
+        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))) {
+            virBufferVSprintf(&buf, "  <seclabel type='%s' model='%s'/>\n",
+                              sectype, def->seclabel.model);
+        } else {
+            virBufferVSprintf(&buf, "  <seclabel type='%s' model='%s'>\n",
+                                  sectype, def->seclabel.model);
+            virBufferEscapeString(&buf, "    <label>%s</label>\n",
+                                  def->seclabel.label);
+            if (def->seclabel.imagelabel &&
+                def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
+                virBufferEscapeString(&buf, "    <imagelabel>%s</imagelabel>\n",
+                                      def->seclabel.imagelabel);
+            virBufferAddLit(&buf, "  </seclabel>\n");
+        }
     }
 
     virBufferAddLit(&buf, "</domain>\n");
Index: src/domain_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.h,v
retrieving revision 1.39
diff -u -p -r1.39 domain_conf.h
--- src/domain_conf.h	3 Mar 2009 09:44:42 -0000	1.39
+++ src/domain_conf.h	3 Mar 2009 16:36:17 -0000
@@ -410,6 +410,13 @@ struct _virDomainOSDef {
     char *bootloaderArgs;
 };
 
+enum virDomainSeclabelType {
+    VIR_DOMAIN_SECLABEL_DYNAMIC,
+    VIR_DOMAIN_SECLABEL_STATIC,
+
+    VIR_DOMAIN_SECLABEL_LAST,
+};
+
 /* Security configuration for domain */
 typedef struct _virSecurityLabelDef virSecurityLabelDef;
 typedef virSecurityLabelDef *virSecurityLabelDefPtr;
@@ -417,6 +424,7 @@ struct _virSecurityLabelDef {
     char *model;        /* name of security model */
     char *label;        /* security label string */
     char *imagelabel;   /* security image label string */
+    int type;
 };
 
 #define VIR_DOMAIN_CPUMASK_LEN 1024
@@ -650,5 +658,6 @@ VIR_ENUM_DECL(virDomainInputBus)
 VIR_ENUM_DECL(virDomainGraphics)
 /* from libvirt.h */
 VIR_ENUM_DECL(virDomainState)
+VIR_ENUM_DECL(virDomainSeclabel)
 
 #endif /* __DOMAIN_CONF_H */
Index: src/qemu_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_driver.c,v
retrieving revision 1.213
diff -u -p -r1.213 qemu_driver.c
--- src/qemu_driver.c	3 Mar 2009 15:18:24 -0000	1.213
+++ src/qemu_driver.c	3 Mar 2009 16:36:18 -0000
@@ -1314,9 +1314,9 @@ static int qemudStartVMDaemon(virConnect
     hookData.vm = vm;
     hookData.driver = driver;
 
-   /* If you are using a SecurityDriver and there was no security label in
-      database, then generate a security label for isolation */
-    if (vm->def->seclabel.label == NULL &&
+   /* If you are using a SecurityDriver with dynamic labelling, 
+      then generate a security label for isolation */
+    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
         driver->securityDriver &&
         driver->securityDriver->domainGenSecurityLabel &&
         driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
@@ -1525,6 +1525,13 @@ static void qemudShutdownVMDaemon(virCon
     if (driver->securityDriver)
         driver->securityDriver->domainRestoreSecurityLabel(conn, vm);
 
+    /* Clear out dynamically assigned labels */
+    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+        VIR_FREE(vm->def->seclabel.model);
+        VIR_FREE(vm->def->seclabel.label);
+        VIR_FREE(vm->def->seclabel.imagelabel);
+    }
+
     if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
         VIR_WARN(_("Failed to remove domain status for %s"),
                  vm->def->name);

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list