-----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: