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

Daniel P. Berrange berrange at redhat.com
Tue Feb 24 15:31:57 UTC 2009


On Fri, Feb 20, 2009 at 01:52:31PM -0500, Daniel J Walsh wrote:

>  
> +    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)

Opening local files in virt-install code is an approach we're trying to
get rid of, because it prevents you doing remote provisioning. eg running
virt-install on your laptop to provision on a server in the data center.


> +    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)

Now that I look at this I'm not so sure its a good idea to have the
client code responsible for allocating the 'mcs' level part of the
label. I think virt-install should only specify the first bit of
the label 'root:system_r:qemu_t' and that libvirt should be doing
allocation of the mcs level on the fly at domain startup.

For sVirt 1.0 our assumption is that mcs levels will only be unique
within scope of running VMs on a each host machine. If we are including
the mcs level in the label we pass into the XML, we are going to create
a number of headaches for ourselves. 

 - The inactive config written in /etc/libvirt/qemu contains an
   allocate mcs level even though it doesn't need it unless it is
   running.
 - If someone copies this config to another machine, then the mcs
   level in the config may no longer be unique on the target machine
 - If you live migrate a VM, again you have problem that the mcs used
   on the source may already be in use on the target.
 - Save/restore across machines also has uniqueness issues

The way virt-install is allocating the mcs level here is also open to
race condition if more than one VM provisioning operation is taking
place concurrently.

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