Index: root/xen-unstable.hg/tools/xm-test/tests/Makefile.am =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/tests/Makefile.am +++ root/xen-unstable.hg/tools/xm-test/tests/Makefile.am @@ -19,6 +19,7 @@ SUBDIRS = \ pause \ reboot \ sched-credit \ + security-acm \ sedf \ shutdown \ sysrq \ Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/01_security-acm_basic.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/01_security-acm_basic.py @@ -0,0 +1,118 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger +# +# A couple of simple tests that test ACM security extensions +# for the xm tool. The following xm subcommands are tested: +# +# - makepolicy +# - labels +# - rmlabel +# - addlabel +# - getlabel +# - resources + +from XmTestLib import * +from xen.util import security +import commands +import os +import re + +testpolicy = "xm-test" +testlabel = "blue" +vmconfigfile = "/tmp/xm-test.conf" +testresource = "phy:ram0" + +status, output = traceCommand("xm makepolicy %s" % (testpolicy)) +if status != 0 or output != "": + FAIL("'xm makepolicy' failed with status %d and output\n%s" % + (status,output)); + +status, output = traceCommand("xm labels %s" % (testpolicy)) +if status != 0: + FAIL("'xm labels' failed with status %d.\n" % status) + +#Need to get a vm config file - just have it written to a file +domain = XmTestDomain() +domain.config.write(vmconfigfile) + +#Whatever label it might have - remove it +status, output = traceCommand("xm rmlabel dom %s" % + (vmconfigfile)) + +status, output = traceCommand("xm addlabel %s dom %s %s" % + (testlabel, vmconfigfile, testpolicy)) +if status != 0: + FAIL("'xm addlabel' failed with status %d.\n" % status) + +status, output = traceCommand("xm getlabel dom %s" % + (vmconfigfile)) + +if status != 0: + FAIL("'xm getlabel' failed with status %d, output:\n%s" % + (status, output)) +if output != "policy=%s,label=%s" % (testpolicy,testlabel): + FAIL("Received unexpected output from 'xm getlabel': \n%s" % + (output)) + + +status, output = traceCommand("xm rmlabel dom %s" % + (vmconfigfile)) + +if status != 0: + FAIL("'xm rmlabel' failed with status %d, output: \n%s" % + (status,output)) +if output != "": + FAIL("Received unexpected output from 'xm rmlabel': \n%s" % + (output)) + +status, output = traceCommand("xm getlabel dom %s" % + (vmconfigfile)) + +if output != "Error: 'Domain not labeled'": + FAIL("Received unexpected output from 'xm getlabel': \n%s" % + (output)) + +#Whatever label the resource might have, remove it +status, output = traceCommand("xm rmlabel res %s" % + (testresource)) + +status, output = traceCommand("xm addlabel %s res %s %s" % + (testlabel, testresource, testpolicy)) +if status != 0: + FAIL("'xm addlabel' on resource failed with status %d.\n" % status) + +status, output = traceCommand("xm getlabel res %s" % (testresource)) + +if status != 0: + FAIL("'xm getlabel' on resource failed with status %d, output:\n%s" % + (status, output)) +if output != "policy=%s,label=%s" % (testpolicy,testlabel): + FAIL("Received unexpected output from 'xm getlabel': \n%s" % + (output)) + +status, output = traceCommand("xm resources") + +if status != 0: + FAIL("'xm resources' did not run properly") +if not re.search(security.unify_resname(testresource), output): + FAIL("'xm resources' did not show the tested resource '%s'." % + testresource) + +status, output = traceCommand("xm rmlabel res %s" % + (testresource)) + +if status != 0: + FAIL("'xm rmlabel' on resource failed with status %d, output: \n%s" % + (status,output)) +if output != "": + FAIL("Received unexpected output from 'xm rmlabel': \n%s" % + (output)) + +status, output = traceCommand("xm getlabel res %s" % + (testresource)) + +if output != "Error: 'Resource not labeled'": + FAIL("Received unexpected output from 'xm getlabel': \n%s" % + (output)) Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/Makefile.am =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/Makefile.am @@ -0,0 +1,25 @@ +SUBDIRS = + +TESTS = 01_security-acm_basic.test \ + 02_security-acm_dom_start.test \ + 03_security-acm_dom_conflict.test \ + 04_security-acm_dom_res.test \ + 05_security-acm_dom_res_conf.test \ + 06_security-acm_dom_block_attach.test + +XFAIL_TESTS = + +EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) acm_utils.py +TESTS_ENVIRONMENT=@TENV@ + +%.test: %.py + cp $< $@ + chmod +x $@ + @cp -f xm-test-security_policy.xml /etc/xen/acm-security/policies + +clean-local: am_config_clean-local + +am_config_clean-local: + rm -f *test + rm -f *log + rm -f *~ Index: root/xen-unstable.hg/tools/xm-test/configure.ac =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/configure.ac +++ root/xen-unstable.hg/tools/xm-test/configure.ac @@ -38,6 +38,20 @@ fi AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue) AC_SUBST(ENABLE_HVM) +AC_ARG_ENABLE(full-labeling, + [[ --enable-full-labeling allows the test suite to label all resources]], + [ + ENABLE_LABELING=True + ],[ + ENABLE_LABELING=False + ]) + +if test "x$ENABLE_LABELING" = "xTrue"; then + echo "ACM_LABEL_RESOURCES = True" > lib/XmTestLib/acm_config.py +else + rm -f lib/XmTestLib/acm_config.py* +fi + # Network needs to know ips to use: dhcp or a range of IPs in the form # of: 192.168.1.1-192.168.1.100 # If not dhcp, a netmask and network address must be supplied. Defaults to @@ -127,6 +141,7 @@ AC_CONFIG_FILES([ tests/restore/Makefile tests/save/Makefile tests/sched-credit/Makefile + tests/security-acm/Makefile tests/sedf/Makefile tests/shutdown/Makefile tests/sysrq/Makefile Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py @@ -0,0 +1,64 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger +# +# Simple test that starts two labeled domains; both domains should start +# +# The following xm subcommands are tested: +# - dumppolicy +# - labels + +from XmTestLib import * +from acm_utils import * +import commands +import os + +testlabel1 = "green" +testlabel2 = "red" + +status, output = traceCommand("xm labels") + +labels = ["SystemManagement", "blue", "red", "green"] +for l in labels: + if not re.search(l, output): + FAIL("Label '%s' not found in current policy!", l) + +status, output = traceCommand("xm dumppolicy") +if status != 0: + FAIL("'xm dumppolicy' returned an error code.") +lines = ["ssidref 0: 00 00 00 00", + "ssidref 1: 01 00 00 00", + "ssidref 2: 00 01 00 00", + "ssidref 3: 00 00 01 00", + "ssidref 4: 00 00 00 01"] +for l in lines: + if not re.search(l, output): + FAIL("Could not find '%s' in output of 'xm dumppolicy'" % l) + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)} +verbose = True +domain1 = XmTestDomain(name="domain-%s" % testlabel1, + extraConfig=config) + +try: + domain1.start(noConsole=True) +except DomainError, e: + if verbose: + print e.extra + FAIL("Unable to start 1st labeled test domain.") + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2)} + +domain2 = XmTestDomain(name="domain-%s" % testlabel2, + extraConfig=config) + +try: + domain2.start(noConsole=True) +except DomainError, e: + if verbose: + print e.extra + FAIL("Unable to start 2nd labeled test domain.") + +domain2.destroy() +domain1.destroy() Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenDomain.py =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenDomain.py +++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenDomain.py @@ -102,6 +102,8 @@ class XenConfig: self.defaultOpts["disk"] = [] self.defaultOpts["vif"] = [] self.defaultOpts["vtpm"] = [] + if isACMEnabled(): + self.defaultOpts["access_control"] = [] self.opts = self.defaultOpts Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/xm-test-security_policy.xml =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/xm-test-security_policy.xml @@ -0,0 +1,110 @@ + + + + + xm-test + Fri Sep 29 14:44:38 2006 + + + + + SystemManagement + green + red + blue + + + + + + SystemManagement + green + red + blue + + + + + blue + red + + + + + + + + SystemManagement + + SystemManagement + green + red + blue + + + SystemManagement + + + + + green + + green + + + green + + + + + red + + red + + + red + + + + + blue + + blue + + + blue + + + + + + + SystemManagement + + SystemManagement + + + + + green + + green + + + + + red + + red + + + + + blue + + blue + + + + + Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py @@ -0,0 +1,60 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger +# +# A test that exercises the conflict set of the chinese wall policy. +# Start a first domain and then a second one. The second one is +# expected NOT to be starteable. + +from XmTestLib import * +from acm_utils import * +import commands +import os + +testlabel1 = "blue" +testlabel2 = "red" + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)} + +domain1 = XmTestDomain(name="domain-%s" % testlabel1, + extraConfig=config) + +try: + domain1.start(noConsole=True) +except DomainError, e: + if verbose: + print e.extra + FAIL("Unable to start 1st labeled test domain") + +# Verify with xm dry-run +status, output = traceCommand("xm dry-run /tmp/xm-test.conf | " + "grep -v \"Dry Run\"") +if status != 0: + FAIL("'xm dry-run' failed") +if not re.search("PERMITTED", output): + FAIL("'xm dry-run' did not succeed.") + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2)} + +domain2 = XmTestDomain(name="domain-%s" % testlabel2, + extraConfig=config) + +try: + domain2.start(noConsole=True) + # Should never get here! + FAIL("Could start a domain in a conflict set - " + "this should not be possible") +except DomainError, e: + #This is exactly what we want in this case + status = 0 + +# Verify with xm dry-run +status, output = traceCommand("xm dry-run /tmp/xm-test.conf | " + "grep -v \"Dry Run\"") +if status != 0: + FAIL("'xm dry-run' failed.") +if not re.search("PERMITTED", output): + FAIL("'xm dry-run' did not show that operation was permitted.") + +domain1.destroy() Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/acm_utils.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/acm_utils.py @@ -0,0 +1,15 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger + +from XmTestLib import * +from XmTestLib.acm import * + +testpolicy = "xm-test" +vmconfigfile = "/tmp/xm-test.conf" + +if not isACMEnabled(): + SKIP("Not running this test since ACM not enabled.") + +ACMLoadPolicy(testpolicy) Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py @@ -0,0 +1,69 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger +# +# Simple test that starts two labeled domains using labeled resources each +# + +from XmTestLib import * +from acm_utils import * +import commands +import os + +testlabel1 = "green" +resource1 = "phy:ram0" +testlabel2 = "red" +resource2 = "phy:/dev/ram1" + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1), + "disk" :"%s,hda1,w" % (resource1)} +domain1 = XmTestDomain(name="domain-%s" % testlabel1, + extraConfig=config) + +# Explicity label the resource +ACMLabelResource(resource1, testlabel1) + +try: + domain1.start(noConsole=True) +except DomainError, e: + if verbose: + print e.extra + FAIL("Unable to start 1st labeled test domain.") + +# Verify with xm dry-run +status, output = traceCommand("xm dry-run /tmp/xm-test.conf | " + "grep -v \"Dry Run\"") + +if status != 0: + FAIL("'xm dry-run' failed") +if not re.search("%s: PERMITTED" % resource1, output): + FAIL("'xm dry-run' did not succeed.") + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2), + "disk" :"%s,hda1,w" % (resource2)} + +domain2 = XmTestDomain(name="domain-%s" % testlabel2, + extraConfig=config) + +# Explicity label the resource +ACMLabelResource(resource2, testlabel2) + +try: + domain2.start(noConsole=True) +except DomainError, e: + if verbose: + print e.extra + FAIL("Unable to start 2nd labeled test domain.") + +# Verify with xm dry-run +status, output = traceCommand("xm dry-run /tmp/xm-test.conf | " + "grep -v \"Dry Run\"") + +if status != 0: + FAIL("'xm dry-run' failed") +if not re.search("%s: PERMITTED" % resource2, output): + FAIL("'xm dry-run' did not succeed.") + +domain2.destroy() +domain1.destroy() Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger +# +# A test that tries to start a domain using a resource that it is +# not supposed to be able to use due to its labeling + +from XmTestLib import * +from acm_utils import * +import commands +import os + +testlabel1 = "blue" +resource1 = "phy:ram0" + +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1), + "disk" :"%s,hda1,w" % (resource1)} + +domain1 = XmTestDomain(name="domain-%s" % testlabel1, + extraConfig=config) + +ACMLabelResource(resource1,"red") + +try: + domain1.start(noConsole=True) + # Should never get here + FAIL("Could start domain with resource that it is not supposed to access.") +except DomainError, e: + #That's exactly what we want to have in this case + dummy = 0 + +# Verify via dry-run +status, output = traceCommand("xm dry-run /tmp/xm-test.conf | " + "grep -v \"Dry Run\"") +if not re.search("%s: DENIED" %resource1, output): + FAIL("'xm dry-run' did not show expected result that operation was NOT " + "permitted: \n%s" % output) Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/acm.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/acm.py @@ -0,0 +1,80 @@ +#!/usr/bin/python +""" + Copyright (C) International Business Machines Corp., 2006 + Author: Stefan Berger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; under version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +from Test import * +from xen.util import security + +try: + from acm_config import * +except: + ACM_LABEL_RESOURCES = False + +labeled_resources = {} +acm_verbose = False + +def isACMEnabled(): + return security.on() + + +def ACMLoadPolicy(policy='xm-test'): + s, o = traceCommand("xm makepolicy %s" % (policy)) + if s != 0: + FAIL("Need to be able to do 'xm makepolicy %s' but could not" % + (policy)) + s, o = traceCommand("xm loadpolicy %s" % (policy)) + if s != 0: + FAIL("Could not load the required policy '%s'.\n" + "Start the system without any policy.\n%s" % + (policy, o)) + + +# Applications may label resources explicitly by calling this function +def ACMLabelResource(resource, label='red'): + if acm_verbose: + print "labeling resource %s with label %s" % (resource, label) + if not ACM_LABEL_RESOURCES: + SKIP("Skipping test since not allowed to label resources in " + "test suite") + if not isACMResourceLabeled(resource): + ACMUnlabelResource(resource) + s, o = traceCommand("xm addlabel %s res %s" % (label, resource)) + if s != 0: + FAIL("Could not add label to resource") + else: + labeled_resources["%s" % resource] = 1 + + +# Application may remove a label from a resource. It has to call this +# function and must do so once a resource for re-labeling a resource +def ACMUnlabelResource(resource): + s, o = traceCommand("xm rmlabel res %s" % (resource)) + labeled_resources["%s" % resource] = 0 + + +def isACMResourceLabeled(resource): + """ Check whether a resource has been labeled using this API + and while running the application """ + try: + if labeled_resources["%s" % resource] == 1: + if acm_verbose: + print "resource %s already labeled!" % resource + return True + except: + return False + return False Index: root/xen-unstable.hg/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py @@ -0,0 +1,82 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2005 +# Author: Stefan Berger +# Based on block-create/01_block_attach_device_pos.py +# +# Create a domain and attach 2 resources to it. The first resource +# should be attacheable, the 2nd one should not be due to the label it has. + +import re +from XmTestLib import * +from XmTestLib import block_utils +from acm_utils import * + +testlabel1 = "blue" +resource1 = "phy:ram1" +resourcelabel1 = "blue" +resource2 = "phy:/dev/ram0" +resourcelabel2 = "red" + +if ENABLE_HVM_SUPPORT: + SKIP("Block-attach not supported for HVM domains") + +# Create a domain (default XmTestDomain, with our ramdisk) +config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)} + +domain = XmTestDomain(extraConfig=config) + +try: + console = domain.start() +except DomainError, e: + FAIL(str(e)) + +# Attach a console to it +try: + console.setHistorySaveCmds(value=True) + # Run 'ls' + run = console.runCmd("ls") +except ConsoleError, e: + saveLog(console.getHistory()) + FAIL(str(e)) + + +# Explicitly label the 1st resource +ACMLabelResource(resource1, resourcelabel1) +block_utils.block_attach(domain, resource1, "sdb1") + +try: + run1 = console.runCmd("cat /proc/partitions") +except ConsoleError, e: + FAIL(str(e)) + +#Explicitly label the 2nd resource +ACMLabelResource(resource2, resourcelabel2) +#Cannot call block_attach here since we legally may fail the command +status, output = traceCommand("xm block-attach %s %s %s w" % + (domain.getName(), resource2, "sdb2" )) + +for i in range(10): + if block_utils.get_state(domain, "sdb2") == 4: + break + time.sleep(1) + +try: + run2 = console.runCmd("cat /proc/partitions") +except ConsoleError, e: + FAIL(str(e)) + +# Close the console +domain.closeConsole() + +# Stop the domain (nice shutdown) +domain.stop() + +if not re.search("sdb1",run1["output"]): + FAIL("Labeled device 'sdb1' is not actually connected to the domU") + +if not re.search("sdb1",run2["output"]): + FAIL("Labeled device 'sdb1' has disappeared?!") + +if re.search("sdb2",run2["output"]): + FAIL("Labeled device 'sdb2' is connected to the domU but should not be") Index: root/xen-unstable.hg/tools/xm-test/README =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/README +++ root/xen-unstable.hg/tools/xm-test/README @@ -112,6 +112,38 @@ Xm-test will look for disk.img in the ra default. +BUILDING for ACM Security Testing +================================= + +A number of tests have been added to test the access control module (ACM) +in the Xen hypervisor and the tools for supporting ACM. Those tests are +located in the security-acm directory. If ACM support is compiled into Xen +(see the user guide for how to do this) those tests can be run with the +following command from the xm-test directory + +./runtest.sh [...] -g security + +Some of these tests will work even without support of ACM by Xen. + +Several of these tests require the privilege of being allowed to label +resources and will otherwise be skipped. By default the test suite +is not allowed to automatically label resources since this may affect +existing labels. To enable this, the test suite must be configured with +the following parameter passed to the configure scripts (in addition to +any other desired parameters) + +./configure --enable-full-labeling + +To revoke the privilege at a later time run the configure scripts without +this parameter: + +./configure + +If a 'make' has previously been run for building the test suite, it is not +necessary to run 'make' again just for enabling or disabling the automatic +labeling of resources. + + Running ======= Index: root/xen-unstable.hg/tools/xm-test/grouptest/default =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/grouptest/default +++ root/xen-unstable.hg/tools/xm-test/grouptest/default @@ -22,6 +22,7 @@ reboot restore save sched-credit +security-acm shutdown sysrq unpause Index: root/xen-unstable.hg/tools/xm-test/grouptest/security =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/grouptest/security @@ -0,0 +1 @@ +security-acm