[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] Patch to python-virtinst to allow it to choose svirt labels



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Also found at least one big bug in python-virtinst, VirtualDisk.py was
dropping the "/" between dirname and basename of installation object,
when you told it to create the object.

I think we want to have a big switch stored in libvirt somewhere saying
whether or not we want isolated virtual machines.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkme++4ACgkQrlYvE4MpobM5ewCeP3iaq3HwT/Rw71E2YElbxKyg
66gAoJaCUkQkBvJz80wjztYiwOGsAKaj
=GlDN
-----END PGP SIGNATURE-----
diff -r -u virtinst-0.400.1/virtinst/Guest.py virtinst-0.400.1.new/virtinst/Guest.py
--- virtinst-0.400.1/virtinst/Guest.py	2009-01-26 14:33:25.000000000 -0500
+++ virtinst-0.400.1.new/virtinst/Guest.py	2009-02-19 17:36:35.000000000 -0500
@@ -32,6 +32,8 @@
 import __builtin__
 import CapabilitiesParser
 import VirtualDevice
+import selinux
+import random
 
 import osdict
 from VirtualDisk import VirtualDisk
@@ -315,8 +317,9 @@
         self._install_disk = None   # VirtualDisk that contains install media
 
         if type is None:
-            type = "xen"
-        self.type = type
+            self.type = "xen"
+        else:
+            self.type = type
 
         if not location is None:
             self.location = location
@@ -526,6 +529,7 @@
         self._vcpus = None
         self._cpuset = None
         self._graphics_dev = None
+        self._seclabel = None
 
         self._os_type = None
         self._os_variant = None
@@ -552,12 +556,34 @@
 
         self.disknode = None # this needs to be set in the subclass
 
+        self.default_seclabel , self.default_imagelabel =  self._default_seclabels()
+
+        while self._seclabel == None:
+            seclabel, imagelabel = self.gen_seclabels()
+            if self.is_conflict_seclabel(self.conn, seclabel):
+                continue
+            self.set_seclabel(seclabel)
+            self.set_imagelabel(imagelabel)
+
     def get_installer(self):
         return self._installer
     def set_installer(self, val):
         self._installer = val
     installer = property(get_installer, set_installer)
 
+    # Security context used to secure guest image 
+    def get_imagelabel(self):
+        return self._imagelabel
+    def set_imagelabel(self, val):
+        self._imagelabel = val
+    imagelabel = property(get_imagelabel, set_imagelabel)
+
+    # Security context used to secure guest process
+    def get_seclabel(self):
+        return self._seclabel
+    def set_seclabel(self, val):
+        self._seclabel = val
+    seclabel = property(get_seclabel, set_seclabel)
 
     def get_type(self):
         return self._installer.type
@@ -565,7 +591,6 @@
         self._installer.type = val
     type = property(get_type, set_type)
 
-
     # Domain name of the guest
     def get_name(self):
         return self._name
@@ -750,7 +775,7 @@
         if enabled not in (True, False):
             raise ValueError, _("Graphics enabled must be True or False")
 
-        if enabled == True:
+        if enabled:
             gdev = VirtualGraphics(type=gtype)
             if port:
                 gdev.port = port
@@ -807,9 +832,23 @@
         """Ensure that devices are setup"""
         for disk in self._install_disks:
             disk.setup(progresscb)
+            # Not sure of this, might want to put this in VirtualDisk class
+            selinux.setfilecon(disk.path, self._imagelabel)
         for nic in self._install_nics:
             nic.setup(self.conn)
 
+    def _get_seclabel_xml(self):
+        xml = ""
+        if self._seclabel != None:
+            xml = """
+  <seclabel model='selinux'>
+    <label>%s</label>
+    <image>%s</image>
+  </seclabel>
+""" % ( self._seclabel, self._imagelabel)
+            print xml
+        return xml
+
     def _get_disk_xml(self, install=True):
         """Return xml for disk devices (Must be implemented in subclass)"""
         raise NotImplementedError
@@ -899,6 +938,7 @@
   <devices>
 %(devices)s
   </devices>
+  %(secxml)s
 </domain>
 """ % { "type": self.type,
         "name": self.name, \
@@ -909,7 +949,8 @@
         "maxramkb": self.maxmemory * 1024, \
         "devices": self._get_device_xml(install), \
         "osblob": osblob, \
-        "action": action }
+        "action": action, \
+        "secxml": self._get_seclabel_xml()}
 
 
     def start_install(self, consolecb=None, meter=None, removeOld=False,
@@ -1026,6 +1067,108 @@
         if self.domain is not None:
             raise RuntimeError, _("Domain has already been started!")
 
+    def _default_seclabels(self):
+        try:
+            fd = open(selinux.selinux_virtual_domain_context_path(), 'r')
+        except OSError, (err_no, msg):
+            raise RuntimeError, \
+                "failed to SELinux virtual domains context: %s: %s %s" % (selinux.selinux_virtual_domain_context_path(),err_no, msg)
+
+        label = fd.read()
+        fd.close()
+        try:
+            fd = open(selinux.selinux_virtual_image_context_path(), 'r')
+        except OSError, (err_no, msg):
+            raise RuntimeError, \
+                "failed to SELinux virtual domains context: %s: %s %s" % (selinux.selinux_virtual_domain_context_path(), err_no, msg)
+
+        image = fd.read()
+        fd.close()
+
+        return (label, image)
+
+    def is_conflict_seclabel(self, conn, seclabel):
+        """
+        check if security label is in use by any other VMs on passed
+        connection.
+
+        @param conn: connection to check for collisions on
+        @type conn: libvirt.virConnect
+
+        @param seclabel: Security Label 
+        @type str: Security label 
+
+        @return: True if a collision, False otherwise
+        @rtype: C{bool}
+        """
+        if not seclabel:
+            return False
+
+        vms = []
+        # get working domain's name
+        ids = conn.listDomainsID()
+        for i in ids:
+            try:
+                vm = conn.lookupByID(i)
+                vms.append(vm)
+            except libvirt.libvirtError:
+                # guest probably in process of dieing
+                logging.warn("Failed to lookup domain id %d" % i)
+        # get defined domain
+        names = conn.listDefinedDomains()
+        for name in names:
+            try:
+                vm = conn.lookupByName(name)
+                vms.append(vm)
+            except libvirt.libvirtError:
+                # guest probably in process of dieing
+                logging.warn("Failed to lookup domain name %s" % name)
+
+        count = 0
+        for vm in vms:
+            doc = None
+            try:
+                doc = libxml2.parseDoc(vm.XMLDesc(0))
+            except:
+                continue
+            ctx = doc.xpathNewContext()
+            try:
+                try:
+                    label = ctx.xpathEval("/domain/seclabel/label/")
+                    if label[0].content == seclabel:
+                        count += 1
+                        break
+                except:
+                    continue
+            finally:
+                if ctx is not None:
+                    ctx.xpathFreeContext()
+                if doc is not None:
+                    doc.freeDoc()
+        if count > 0:
+            return True
+        else:
+            return False
+
+    def _get_random_mcs(self):
+        f1 = random.randrange(1024)
+        f2 = random.randrange(1024)
+        if f1 < f2:
+            return "s0:c%s,c%s" % (f1, f2)
+        else:
+            if f1 == f2:
+                return "s0:c%s" % f1
+            else:
+                return "s0:c%s,c%s" % (f2, f1)
+
+    def gen_seclabels(self):
+        mcs = self._get_random_mcs()
+        con = self.default_seclabel.split(':')
+        seclabel = "%s:%s:%s:%s" %  (con[0], con[1], con[2], mcs)
+        con = self.default_imagelabel.split(':')
+        imagelabel = "%s:%s:%s:%s" %  (con[0], con[1], con[2], mcs)
+        return (seclabel, imagelabel)
+            
     def _set_defaults(self):
         if self.uuid is None:
             while 1:
diff -r -u virtinst-0.400.1/virtinst/VirtualDisk.py virtinst-0.400.1.new/virtinst/VirtualDisk.py
--- virtinst-0.400.1/virtinst/VirtualDisk.py	2009-01-26 14:33:25.000000000 -0500
+++ virtinst-0.400.1.new/virtinst/VirtualDisk.py	2009-02-19 19:43:44.000000000 -0500
@@ -172,8 +172,6 @@
         """
         return "%s:%s" %(self.type, self.path)
 
-
-
     def _get_path(self):
         return self._path
     def _set_path(self, val, validate=True):
@@ -413,7 +411,7 @@
             newpath = self.vol_object.path()
         elif self.vol_install:
             newpath = _util.get_xml_path(self.vol_install.pool.XMLDesc(0),
-                                         "/pool/target/path") + \
+                                         "/pool/target/path") + "/" + \
                       self.vol_install.name
 
         if newpath and newpath != self.path:

Attachment: virtinst-0.400.1-svirt.patch.sig
Description: PGP signature


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]