WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [Patch 7 / 8][XM] - Xen Management integration

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [Patch 7 / 8][XM] - Xen Management integration
From: Reiner Sailer <sailer@xxxxxxxxxx>
Date: Tue, 11 Apr 2006 22:29:04 -0400
Cc: sailer@xxxxxxxxxx
Delivery-date: Tue, 11 Apr 2006 19:32:57 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla Thunderbird 1.0.7 (Windows/20050923)
This patch integrates the new access control management tools into 'xm' and 'xend' and supports label/ssid translation support for migration/life-migration/resume.

Signed-off by: Reiner Sailer <sailer@xxxxxxxxxx>

---
 tools/python/xen/xend/XendDomain.py     |    4 +
 tools/python/xen/xend/XendDomainInfo.py |   56 ++++++++++++++++------
 tools/python/xen/xm/create.py           |   81 +++++++++++++++++++++++++++++---
 tools/python/xen/xm/main.py             |   69 +++++++++++++++++++++++----
 4 files changed, 178 insertions(+), 32 deletions(-)

Index: xen-unstable.hg-shype/tools/python/xen/xend/XendDomain.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xend/XendDomain.py
+++ xen-unstable.hg-shype/tools/python/xen/xend/XendDomain.py
@@ -38,6 +38,7 @@ from xen.xend.XendError import XendError
 from xen.xend.XendLogging import log
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.xenstore.xswatch import xswatch
+from xen.util import security
 
 
 xc = xen.lowlevel.xc.xc()
@@ -265,7 +266,7 @@ class XendDomain:
             # handling in the relocation-socket handling code (relocate.py) is
             # poor, so we need to log this for debugging.
             log.exception("Restore failed")
-            raise
+            raise XendError("Restore failed")
 
 
     def restore_(self, config):
@@ -283,6 +284,7 @@ class XendDomain:
         """
         self.domains_lock.acquire()
         try:
+            security.refresh_ssidref(config)
             dominfo = XendDomainInfo.restore(config)
             self._add_domain(dominfo)
             return dominfo
Index: xen-unstable.hg-shype/tools/python/xen/xend/XendDomainInfo.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xend/XendDomainInfo.py
+++ xen-unstable.hg-shype/tools/python/xen/xend/XendDomainInfo.py
@@ -33,7 +33,7 @@ import threading
 import xen.lowlevel.xc
 from xen.util import asserts
 from xen.util.blkif import blkdev_uname_to_file
-
+from xen.util import security
 import balloon
 import image
 import sxp
@@ -120,7 +120,6 @@ VM_CONFIG_PARAMS = [
 # file, so those are handled separately.
 ROUNDTRIPPING_CONFIG_ENTRIES = [
     ('uuid',       str),
-    ('ssidref',    int),
     ('vcpus',      int),
     ('vcpu_avail', int),
     ('cpu_weight', float),
@@ -138,7 +137,6 @@ ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFI
 #
 VM_STORE_ENTRIES = [
     ('uuid',       str),
-    ('ssidref',    int),
     ('vcpus',      int),
     ('vcpu_avail', int),
     ('memory',     int),
@@ -291,6 +289,9 @@ def parseConfig(config):
     result['cpu']   = get_cfg('cpu',  int)
     result['cpus']  = get_cfg('cpus', str)
     result['image'] = get_cfg('image')
+    tmp_security = get_cfg('security')
+    if tmp_security:
+        result['security'] = tmp_security
 
     try:
         if result['image']:
@@ -437,7 +438,7 @@ class XendDomainInfo:
         self.validateInfo()
 
         self.image = None
-
+        self.security = None
         self.store_port = None
         self.store_mfn = None
         self.console_port = None
@@ -515,6 +516,7 @@ class XendDomainInfo:
         else:
             entries = VM_STORE_ENTRIES
         entries.append(('image', str))
+        entries.append(('security', str))
 
         map(lambda x, y: useIfNeeded(x[0], y), entries,
             self.readVMDetails(entries))
@@ -538,7 +540,6 @@ class XendDomainInfo:
 
         try:
             defaultInfo('name',         lambda: "Domain-%d" % self.domid)
-            defaultInfo('ssidref',      lambda: 0)
             defaultInfo('on_poweroff',  lambda: "destroy")
             defaultInfo('on_reboot',    lambda: "restart")
             defaultInfo('on_crash',     lambda: "restart")
@@ -565,12 +566,16 @@ class XendDomainInfo:
             defaultInfo('backend',      lambda: [])
             defaultInfo('device',       lambda: [])
             defaultInfo('image',        lambda: None)
+            defaultInfo('security',     lambda: None)
 
             self.check_name(self.info['name'])
 
             if isinstance(self.info['image'], str):
                 self.info['image'] = sxp.from_string(self.info['image'])
 
+            if isinstance(self.info['security'], str):
+                self.info['security'] = sxp.from_string(self.info['security'])
+
             if self.info['memory'] == 0:
                 if self.infoIsSet('mem_kb'):
                     self.info['memory'] = (self.info['mem_kb'] + 1023) / 1024
@@ -668,6 +673,20 @@ class XendDomainInfo:
         if self.infoIsSet('image'):
             to_store['image'] = sxp.to_string(self.info['image'])
 
+        if self.infoIsSet('security'):
+            security = self.info['security']
+            to_store['security'] = sxp.to_string(security)
+            for idx in range(0, len(security)):
+                if security[idx][0] == 'access_control':
+                    to_store['security/access_control'] = sxp.to_string([ 
security[idx][1] , security[idx][2] ])
+                    for aidx in range(1, len(security[idx])):
+                        if security[idx][aidx][0] == 'label':
+                            to_store['security/access_control/label'] = 
security[idx][aidx][1]
+                        if security[idx][aidx][0] == 'policy':
+                            to_store['security/access_control/policy'] = 
security[idx][aidx][1]
+                if security[idx][0] == 'ssidref':
+                    to_store['security/ssidref'] = str(security[idx][1])
+
         log.debug("Storing VM details: %s", to_store)
 
         self.writeVm(to_store)
@@ -760,9 +779,8 @@ class XendDomainInfo:
         self.storeVm('vcpu_avail', self.info['vcpu_avail'])
         self.writeDom(self.vcpuDomDetails())
 
-
-    def getSsidref(self):
-        return self.info['ssidref']
+    def getLabel(self):
+        return security.get_security_info(self.info, 'label')
 
     def getMemoryTarget(self):
         """Get this domain's target memory size, in KB."""
@@ -954,12 +972,21 @@ class XendDomainInfo:
         """
 
         log.trace("XendDomainInfo.update(%s) on domain %d", info, self.domid)
-
         if not info:
             info = dom_get(self.domid)
             if not info:
                 return
             
+        #manually update ssidref / security fields
+        if security.on() and info.has_key('ssidref'):
+            if (info['ssidref'] != 0) and self.info.has_key('security'):
+                security_field = self.info['security']
+                if not security_field:
+                    #create new security element
+                    self.info.update({'security': [['ssidref', 
str(info['ssidref'])]]})
+            #ssidref field not used any longer
+        info.pop('ssidref')
+
         self.info.update(info)
         self.validateInfo()
         self.refreshShutdown(info)
@@ -996,7 +1023,6 @@ class XendDomainInfo:
         s += " id=" + str(self.domid)
         s += " name=" + self.info['name']
         s += " memory=" + str(self.info['memory'])
-        s += " ssidref=" + str(self.info['ssidref'])
         s += ">"
         return s
 
@@ -1058,6 +1084,9 @@ class XendDomainInfo:
         if self.infoIsSet('image'):
             sxpr.append(['image', self.info['image']])
 
+        if self.infoIsSet('security'):
+            sxpr.append(['security', self.info['security']])
+
         for cls in controllerClasses:
             for config in self.getDeviceConfigurations(cls):
                 sxpr.append(['device', config])
@@ -1159,12 +1188,11 @@ class XendDomainInfo:
         @raise: VmError on error
         """
 
-        log.debug('XendDomainInfo.construct: %s %s',
-                  self.domid,
-                  self.info['ssidref'])
+        log.debug('XendDomainInfo.construct: %s',
+                  self.domid)
 
         self.domid = xc.domain_create(
-            dom = 0, ssidref = self.info['ssidref'],
+            dom = 0, ssidref = security.get_security_info(self.info, 
'ssidref'),
             handle = uuid.fromString(self.info['uuid']))
 
         if self.domid < 0:
Index: xen-unstable.hg-shype/tools/python/xen/xm/create.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xm/create.py
+++ xen-unstable.hg-shype/tools/python/xen/xm/create.py
@@ -35,6 +35,7 @@ import xen.xend.XendClient
 from xen.xend.XendClient import server
 from xen.xend.XendBootloader import bootloader
 from xen.util import blkif
+from xen.util import security
 
 from xen.xm.opts import *
 
@@ -145,10 +146,6 @@ gopts.var('memory', val='MEMORY',
           fn=set_int, default=128,
           use="Domain memory in MB.")
 
-gopts.var('ssidref', val='SSIDREF',
-          fn=set_u32, default=0, 
-          use="Security Identifier.")
-
 gopts.var('maxmem', val='MEMORY',
           fn=set_int, default=None,
           use="Maximum domain memory in MB.")
@@ -293,6 +290,14 @@ gopts.var('vtpm', val="instance=INSTANCE
           number can be found in /etc/xen/vtpm.db. Use the backend in the
           given domain.""")
 
+gopts.var('access_control', val="policy=POLICY,label=LABEL",
+          fn=append_value, default=[],
+          use="""Add a security label and the security policy reference that 
defines it.
+          The local ssid reference is calculated when starting/resuming the 
domain. At
+          this time, the policy is checked against the active policy as well. 
This way,
+          migrating through save/restore is covered and local labels are 
automatically
+          created correctly on the system where a domain is started / 
resumed.""")
+
 gopts.var('nics', val="NUM",
           fn=set_int, default=-1,
           use="""DEPRECATED.  Use empty vif entries instead.
@@ -502,6 +507,43 @@ def configure_usb(config_devs, vals):
         config_usb = ['usb', ['path', path]]
         config_devs.append(['device', config_usb])
 
+
+def configure_security(config, vals):
+    """Create the config for ACM security labels.
+    """
+    access_control = vals.access_control
+    num = len(access_control)
+    if num == 1:
+        d = access_control[0]
+        policy = d.get('policy')
+        label = d.get('label')
+        if policy != security.active_policy:
+            err("Security policy (" + policy + ") incompatible with enforced 
policy ("
+                + security.active_policy + ")." )
+        config_access_control = ['access_control',
+                                 ['policy', policy],
+                                 ['label', label] ]
+
+        #ssidref cannot be specified together with access_control
+        if sxp.child_value(config, 'ssidref'):
+            err("ERROR: SSIDREF and access_control are mutually exclusive but 
both specified!")
+        #else calculate ssidre from label
+        ssidref = security.label2ssidref(label, policy)
+        if not ssidref :
+            err("ERROR calculating ssidref from access_control.")
+        security_label = ['security', [ config_access_control, ['ssidref' , 
ssidref ] ] ]
+        config.append(security_label)
+    elif num == 0:
+        if hasattr(vals, 'ssidref'):
+            if not security.on():
+                err("ERROR: Security ssidref specified but no policy active.")
+            ssidref = getattr(vals, 'ssidref')
+            security_label = ['security', [ [ 'ssidref' , int(ssidref) ] ] ]
+            config.append(security_label)
+    elif num > 1:
+        err("VM config error: Multiple access_control definitions!")
+
+
 def configure_vtpm(config_devs, vals):
     """Create the config for virtual TPM interfaces.
     """
@@ -595,9 +637,9 @@ def make_config(vals):
             if v:
                 config.append([n, v])
 
-    map(add_conf, ['name', 'memory', 'ssidref', 'maxmem', 'restart',
-                   'on_poweroff', 'on_reboot', 'on_crash', 'vcpus'])
-    
+    map(add_conf, ['name', 'memory', 'maxmem', 'restart', 'on_poweroff',
+                   'on_reboot', 'on_crash', 'vcpus'])
+
     if vals.uuid is not None:
         config.append(['uuid', vals.uuid])
     if vals.cpu is not None:
@@ -628,6 +670,7 @@ def make_config(vals):
     configure_vifs(config_devs, vals)
     configure_usb(config_devs, vals)
     configure_vtpm(config_devs, vals)
+    configure_security(config, vals)
     config += config_devs
 
     return config
@@ -696,6 +739,29 @@ def preprocess_vtpm(vals):
         vtpms.append(d)
     vals.vtpm = vtpms
 
+def preprocess_access_control(vals):
+    if not vals.access_control:
+        return
+    access_controls = []
+    num = len(vals.access_control)
+    if num == 1:
+        access_control = (vals.access_control)[0]
+        d = {}
+        a = access_control.split(',')
+        if len(a) > 2:
+            err('Too many elements in access_control specifier: ' + 
access_control)
+        for b in a:
+            (k, v) = b.strip().split('=', 1)
+            k = k.strip()
+            v = v.strip()
+            if k not in ['policy','label']:
+                err('Invalid access_control specifier: ' + access_control)
+            d[k] = v
+        access_controls.append(d)
+        vals.access_control = access_controls
+    elif num > 1:
+        err('Multiple access_control definitions.')
+
 def preprocess_ip(vals):
     if vals.ip or vals.dhcp != 'off':
         dummy_nfs_server = '1.2.3.4'
@@ -785,6 +851,7 @@ def preprocess(vals):
     preprocess_nfs(vals)
     preprocess_vnc(vals)
     preprocess_vtpm(vals)
+    preprocess_access_control(vals)
 
 
 def comma_sep_kv_to_dict(c):
Index: xen-unstable.hg-shype/tools/python/xen/xm/main.py
===================================================================
--- xen-unstable.hg-shype.orig/tools/python/xen/xm/main.py
+++ xen-unstable.hg-shype/tools/python/xen/xm/main.py
@@ -40,6 +40,7 @@ from xen.xm.opts import *
 import console
 import xen.xend.XendClient
 from xen.xend.XendClient import server
+from xen.util import security
 
 # getopt.gnu_getopt is better, but only exists in Python 2.3+.  Use
 # getopt.getopt if gnu_getopt is not available.  This will mean that options
@@ -55,6 +56,8 @@ create_help =  """create [-c] <ConfigFil
 destroy_help = "destroy <DomId>                  Terminate a domain 
immediately"
 help_help =    "help                             Display this message"
 list_help =    "list [--long] [DomId, ...]       List information about 
domains"
+list_label_help = "list [--label] [DomId, ...]      List information about 
domains including their labels"
+
 mem_max_help = "mem-max <DomId> <Mem>            Set maximum memory 
reservation for a domain"
 mem_set_help = "mem-set <DomId> <Mem>            Adjust the current memory 
usage for a domain"
 migrate_help = "migrate <DomId> <Host>           Migrate a domain to another 
machine"
@@ -114,6 +117,12 @@ vnet_list_help = "vnet-list [-l|--long] 
 vnet_create_help = "vnet-create <config>             create a vnet from a 
config file"
 vnet_delete_help = "vnet-delete <vnetid>             delete a vnet"
 vtpm_list_help = "vtpm-list <DomId> [--long]       list virtual TPM devices"
+addlabel_help =  "addlabel <ConfigFile> <label>    Add security label to 
ConfigFile"
+cfgbootpolicy_help = "cfgbootpolicy <policy>           Add policy to boot 
configuration "
+dumppolicy_help = "dumppolicy                       Print hypervisor ACM state 
information"
+loadpolicy_help = "loadpolicy <policy>              Load binary policy into 
hypervisor"
+makepolicy_help = "makepolicy <policy>              Build policy and create 
.bin/.map files"
+labels_help     = "labels [policy] [type=DOM|..]    List <type> labels for 
(active) policy."
 
 short_command_list = [
     "console",
@@ -140,6 +149,7 @@ domain_commands = [
     "domid",
     "domname",
     "list",
+    "list_label",
     "mem-max",
     "mem-set",
     "migrate",
@@ -185,8 +195,17 @@ vnet_commands = [
     "vnet-delete",
     ]
 
+acm_commands = [
+    "labels",
+    "addlabel",
+    "makepolicy",
+    "loadpolicy",
+    "cfgbootpolicy",
+    "dumppolicy"
+    ]
+
 all_commands = (domain_commands + host_commands + scheduler_commands +
-                device_commands + vnet_commands)
+                device_commands + vnet_commands + acm_commands)
 
 
 def commandToHelp(cmd):
@@ -225,6 +244,9 @@ xm full list of subcommands:
   Vnet commands:
    """ + help_spacer.join(map(commandToHelp,  vnet_commands)) + """
 
+  Access Control commands:
+   """ + help_spacer.join(map(commandToHelp,  acm_commands)) + """
+
 <DomName> can be substituted for <DomId> in xm subcommands.
 
 For a short list of subcommands run 'xm help'
@@ -332,8 +354,9 @@ def getDomains(domain_names):
 def xm_list(args):
     use_long = 0
     show_vcpus = 0
+    show_labels = 0
     try:
-        (options, params) = getopt.gnu_getopt(args, 'lv', ['long','vcpus'])
+        (options, params) = getopt.gnu_getopt(args, 'lv', 
['long','vcpus','label'])
     except getopt.GetoptError, opterr:
         err(opterr)
         sys.exit(1)
@@ -343,6 +366,8 @@ def xm_list(args):
             use_long = 1
         if k in ['-v', '--vcpus']:
             show_vcpus = 1
+        if k in ['--label']:
+            show_labels = 1
 
     if show_vcpus:
         print >>sys.stderr, (
@@ -354,6 +379,8 @@ def xm_list(args):
 
     if use_long:
         map(PrettyPrint.prettyprint, doms)
+    elif show_labels:
+        xm_label_list(doms)
     else:
         xm_brief_list(doms)
 
@@ -369,7 +396,7 @@ def parse_doms_info(info):
         'vcpus'    : get_info('online_vcpus', int,   0),
         'state'    : get_info('state',        str,   '??'),
         'cpu_time' : get_info('cpu_time',     float, 0),
-        'ssidref'  : get_info('ssidref',      int,   0),
+        'seclabel' : security.get_security_printlabel(info),
         }
 
 
@@ -391,13 +418,29 @@ def xm_brief_list(doms):
     print 'Name                              ID Mem(MiB) VCPUs State  Time(s)'
     for dom in doms:
         d = parse_doms_info(dom)
-        if (d['ssidref'] != 0):
-            d['ssidstr'] = (" s:%04x/p:%04x" % 
-                            ((d['ssidref'] >> 16) & 0xffff,
-                              d['ssidref']        & 0xffff))
+        print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s 
%(cpu_time)7.1f" % d)
+
+
+def xm_label_list(doms):
+    output = []
+    print 'Name                              ID Mem(MiB) VCPUs State  Time(s)  
Label'
+    for dom in doms:
+        d = parse_doms_info(dom)
+        l = "%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s 
%(cpu_time)7.1f  " % d
+        if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
+            if d['seclabel']:
+                line = (l, d['seclabel'])
+            else:
+                line = (l, "ERROR")
+        elif security.active_policy in ['DEFAULT']:
+            line = (l, "DEFAULT")
         else:
-            d['ssidstr'] = ""
-        print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s 
%(cpu_time)7.1f%(ssidstr)s" % d)
+            line = (l, "INACTIVE")
+        output.append(line)
+    #sort by labels
+    output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
+    for l in output:
+        print l[0] + l[1]
 
 
 def xm_vcpu_list(args):
@@ -1010,7 +1053,13 @@ subcommands = [
     'create',
     'migrate',
     'sysrq',
-    'shutdown'
+    'shutdown',
+    'labels',
+    'addlabel',
+    'cfgbootpolicy',
+    'makepolicy',
+    'loadpolicy',
+    'dumppolicy'
     ]
 
 for c in subcommands:



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [Patch 7 / 8][XM] - Xen Management integration, Reiner Sailer <=