[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg (staging)
# HG changeset patch # User Alex Williamson <alex.williamson@xxxxxx> # Date 1189101915 21600 # Node ID 4ffca478e2f70a3f6674462cbe395560613ff5f2 # Parent 12be90e2f831f1ffabb5a568e5426263079f90ef # Parent 32f331858d751f29b5970dd208c91e9dedea1182 merge with xen-unstable.hg (staging) --- tools/python/xen/util/security.py | 1299 ------- xen/acm/Makefile | 5 xen/acm/acm_chinesewall_hooks.c | 724 ---- xen/acm/acm_core.c | 392 -- xen/acm/acm_null_hooks.c | 95 xen/acm/acm_policy.c | 876 ---- xen/acm/acm_simple_type_enforcement_hooks.c | 914 ----- xen/arch/x86/cpu/mtrr/centaur.c | 223 - xen/arch/x86/cpu/rise.c | 54 xen/common/acm_ops.c | 212 - xen/include/acm/acm_core.h | 196 - xen/include/acm/acm_endian.h | 69 xen/include/acm/acm_hooks.h | 353 - xen/include/public/acm.h | 229 - xen/include/public/acm_ops.h | 159 .hgignore | 3 Config.mk | 11 buildconfigs/mk.linux-2.6-xen | 15 buildconfigs/src.hg-clone | 14 buildconfigs/src.tarball | 4 config/FreeBSD.mk | 1 config/x86_32.mk | 8 docs/misc/dump-core-format.txt | 10 tools/Makefile | 1 tools/Rules.mk | 2 tools/blktap/drivers/tapdisk.c | 4 tools/examples/blktap | 65 tools/examples/block | 42 tools/examples/block-common.sh | 43 tools/examples/network-bridge | 3 tools/firmware/hvmloader/smbios.c | 4 tools/firmware/hvmloader/util.h | 1 tools/firmware/rombios/rombios.c | 11 tools/flask/Makefile | 26 tools/flask/libflask/Makefile | 65 tools/flask/libflask/flask_op.c | 100 tools/flask/libflask/include/flask_op.h | 46 tools/flask/loadpolicy/Makefile | 61 tools/flask/loadpolicy/loadpolicy.c | 130 tools/ioemu/Makefile.target | 1 tools/ioemu/hw/cirrus_vga.c | 7 tools/ioemu/hw/ide.c | 12 tools/ioemu/hw/tpm_tis.c | 24 tools/ioemu/target-i386-dm/exec-dm.c | 21 tools/ioemu/vl.h | 12 tools/libxc/xc_acm.c | 2 tools/libxc/xc_core.c | 467 +- tools/libxc/xc_core.h | 8 tools/libxc/xc_core_ia64.c | 4 tools/libxc/xc_core_ia64.h | 1 tools/libxc/xc_core_powerpc.c | 4 tools/libxc/xc_core_powerpc.h | 1 tools/libxc/xc_core_x86.c | 4 tools/libxc/xc_core_x86.h | 1 tools/libxc/xc_domain.c | 6 tools/libxc/xenctrl.h | 4 tools/misc/xenperf.c | 2 tools/python/Makefile | 26 tools/python/setup.py | 14 tools/python/xen/lowlevel/acm/acm.c | 5 tools/python/xen/lowlevel/flask/flask.c | 139 tools/python/xen/lowlevel/xc/xc.c | 2 tools/python/xen/util/acmpolicy.py | 9 tools/python/xen/util/xsm/__init__.py | 2 tools/python/xen/util/xsm/acm/__init__.py | 1 tools/python/xen/util/xsm/acm/acm.py | 1319 +++++++ tools/python/xen/util/xsm/dummy/__init__.py | 1 tools/python/xen/util/xsm/dummy/dummy.py | 53 tools/python/xen/util/xsm/flask/__init__.py | 1 tools/python/xen/util/xsm/flask/flask.py | 37 tools/python/xen/util/xsm/xsm_core.py | 7 tools/python/xen/xend/XendCheckpoint.py | 31 tools/python/xen/xend/XendConfig.py | 18 tools/python/xen/xend/XendDomainInfo.py | 10 tools/python/xen/xend/XendVDI.py | 3 tools/python/xen/xend/XendXSPolicy.py | 3 tools/python/xen/xend/XendXSPolicyAdmin.py | 3 tools/python/xen/xend/server/BlktapController.py | 8 tools/python/xen/xend/server/blkif.py | 2 tools/python/xen/xend/server/netif.py | 2 tools/python/xen/xm/addlabel.py | 2 tools/python/xen/xm/cfgbootpolicy.py | 10 tools/python/xen/xm/create.py | 11 tools/python/xen/xm/dry-run.py | 2 tools/python/xen/xm/dumppolicy.py | 2 tools/python/xen/xm/getlabel.py | 6 tools/python/xen/xm/labels.py | 6 tools/python/xen/xm/loadpolicy.py | 2 tools/python/xen/xm/main.py | 28 tools/python/xen/xm/makepolicy.py | 2 tools/python/xen/xm/resources.py | 2 tools/python/xen/xm/rmlabel.py | 4 tools/python/xen/xm/setpolicy.py | 2 tools/security/secpol_tool.c | 4 tools/security/secpol_xml2bin.c | 3 tools/xm-test/lib/XmTestLib/acm.py | 2 tools/xm-test/tests/security-acm/01_security-acm_basic.py | 2 tools/xm-test/tests/security-acm/07_security-acm_pol_update.py | 3 tools/xm-test/tests/security-acm/08_security-acm_xapi.py | 3 tools/xm-test/tests/security-acm/09_security-acm_pol_update.py | 3 unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h | 13 xen/Makefile | 6 xen/Rules.mk | 7 xen/arch/ia64/xen/domain.c | 12 xen/arch/ia64/xen/mm.c | 77 xen/arch/ia64/xen/xensetup.c | 2 xen/arch/powerpc/domain.c | 4 xen/arch/powerpc/setup.c | 2 xen/arch/x86/cpu/Makefile | 1 xen/arch/x86/cpu/centaur.c | 380 -- xen/arch/x86/cpu/common.c | 2 xen/arch/x86/cpu/mtrr/Makefile | 1 xen/arch/x86/cpu/mtrr/main.c | 9 xen/arch/x86/domain.c | 122 xen/arch/x86/domain_build.c | 11 xen/arch/x86/domctl.c | 74 xen/arch/x86/e820.c | 9 xen/arch/x86/hvm/hvm.c | 31 xen/arch/x86/hvm/irq.c | 11 xen/arch/x86/hvm/svm/svm.c | 1 xen/arch/x86/hvm/vioapic.c | 2 xen/arch/x86/hvm/vlapic.c | 2 xen/arch/x86/hvm/vmx/vmcs.c | 12 xen/arch/x86/hvm/vmx/vmx.c | 1 xen/arch/x86/mm.c | 39 xen/arch/x86/mm/hap/hap.c | 2 xen/arch/x86/mm/paging.c | 10 xen/arch/x86/mm/shadow/common.c | 101 xen/arch/x86/mm/shadow/multi.c | 114 xen/arch/x86/mm/shadow/private.h | 10 xen/arch/x86/mm/shadow/types.h | 21 xen/arch/x86/physdev.c | 11 xen/arch/x86/platform_hypercall.c | 32 xen/arch/x86/setup.c | 82 xen/arch/x86/sysctl.c | 5 xen/arch/x86/traps.c | 11 xen/arch/x86/x86_32/entry.S | 4 xen/arch/x86/x86_32/mm.c | 15 xen/arch/x86/x86_32/xen.lds.S | 2 xen/arch/x86/x86_64/compat/entry.S | 4 xen/arch/x86/x86_64/entry.S | 5 xen/arch/x86/x86_64/mm.c | 8 xen/common/Makefile | 1 xen/common/domain.c | 78 xen/common/domctl.c | 112 xen/common/event_channel.c | 53 xen/common/grant_table.c | 54 xen/common/kernel.c | 6 xen/common/kexec.c | 5 xen/common/memory.c | 25 xen/common/schedule.c | 8 xen/common/sysctl.c | 21 xen/common/vsprintf.c | 236 + xen/common/xencomm.c | 386 +- xen/common/xenoprof.c | 5 xen/drivers/char/console.c | 5 xen/include/asm-ia64/domain.h | 4 xen/include/asm-ia64/mm.h | 2 xen/include/asm-x86/cpufeature.h | 1 xen/include/asm-x86/domain.h | 18 xen/include/asm-x86/e820.h | 1 xen/include/asm-x86/hvm/vcpu.h | 3 xen/include/asm-x86/msr.h | 7 xen/include/asm-x86/p2m.h | 3 xen/include/asm-x86/paging.h | 16 xen/include/asm-x86/processor.h | 1 xen/include/asm-x86/spinlock.h | 8 xen/include/asm-x86/system.h | 28 xen/include/public/arch-x86/xen.h | 3 xen/include/public/hvm/hvm_op.h | 3 xen/include/public/xen.h | 2 xen/include/public/xsm/acm.h | 229 + xen/include/public/xsm/acm_ops.h | 159 xen/include/public/xsm/flask_op.h | 45 xen/include/xen/domain.h | 2 xen/include/xen/hypercall.h | 10 xen/include/xen/lib.h | 4 xen/include/xen/sched.h | 9 xen/include/xsm/acm/acm_core.h | 196 + xen/include/xsm/acm/acm_endian.h | 69 xen/include/xsm/acm/acm_hooks.h | 349 + xen/include/xsm/xsm.h | 537 ++ xen/xsm/Makefile | 8 xen/xsm/acm/Makefile | 7 xen/xsm/acm/acm_chinesewall_hooks.c | 723 ++++ xen/xsm/acm/acm_core.c | 402 ++ xen/xsm/acm/acm_null_hooks.c | 95 xen/xsm/acm/acm_ops.c | 212 + xen/xsm/acm/acm_policy.c | 876 ++++ xen/xsm/acm/acm_simple_type_enforcement_hooks.c | 914 +++++ xen/xsm/acm/acm_xsm_hooks.c | 74 xen/xsm/dummy.c | 488 ++ xen/xsm/flask/Makefile | 7 xen/xsm/flask/avc.c | 817 ++++ xen/xsm/flask/flask_op.c | 1079 ++++++ xen/xsm/flask/hooks.c | 1159 ++++++ xen/xsm/flask/include/av_inherit.h | 1 xen/xsm/flask/include/av_perm_to_string.h | 99 xen/xsm/flask/include/av_permissions.h | 108 xen/xsm/flask/include/avc.h | 106 xen/xsm/flask/include/avc_ss.h | 14 xen/xsm/flask/include/class_to_string.h | 14 xen/xsm/flask/include/common_perm_to_string.h | 1 xen/xsm/flask/include/conditional.h | 22 xen/xsm/flask/include/flask.h | 36 xen/xsm/flask/include/initial_sid_to_string.h | 18 xen/xsm/flask/include/objsec.h | 33 xen/xsm/flask/include/security.h | 83 xen/xsm/flask/ss/Makefile | 11 xen/xsm/flask/ss/avtab.c | 471 ++ xen/xsm/flask/ss/avtab.h | 85 xen/xsm/flask/ss/conditional.c | 546 +++ xen/xsm/flask/ss/conditional.h | 77 xen/xsm/flask/ss/constraint.h | 61 xen/xsm/flask/ss/context.h | 110 xen/xsm/flask/ss/ebitmap.c | 328 + xen/xsm/flask/ss/ebitmap.h | 79 xen/xsm/flask/ss/hashtab.c | 181 + xen/xsm/flask/ss/hashtab.h | 85 xen/xsm/flask/ss/mls.c | 612 +++ xen/xsm/flask/ss/mls.h | 37 xen/xsm/flask/ss/mls_types.h | 58 xen/xsm/flask/ss/policydb.c | 1798 ++++++++++ xen/xsm/flask/ss/policydb.h | 257 + xen/xsm/flask/ss/services.c | 1657 +++++++++ xen/xsm/flask/ss/services.h | 15 xen/xsm/flask/ss/sidtab.c | 327 + xen/xsm/flask/ss/sidtab.h | 53 xen/xsm/flask/ss/symtab.c | 47 xen/xsm/flask/ss/symtab.h | 23 xen/xsm/xsm_core.c | 118 xen/xsm/xsm_policy.c | 67 232 files changed, 20168 insertions(+), 7149 deletions(-) diff -r 12be90e2f831 -r 4ffca478e2f7 .hgignore --- a/.hgignore Thu Sep 06 09:05:26 2007 -0600 +++ b/.hgignore Thu Sep 06 12:05:15 2007 -0600 @@ -114,6 +114,7 @@ ^tools/firmware/vmxassist/gen$ ^tools/firmware/vmxassist/offsets\.h$ ^tools/firmware/vmxassist/vmxassist$ +^tools/flask/loadpolicy/flask-loadpolicy$ ^tools/ioemu/\.pc/.*$ ^tools/ioemu/config-host\.h$ ^tools/ioemu/config-host\.mak$ @@ -149,8 +150,10 @@ ^tools/misc/xenperf$ ^tools/pygrub/build/.*$ ^tools/python/build/.*$ +^tools/python/xen/util/xsm/xsm\.py$ ^tools/security/secpol_tool$ ^tools/security/xen/.*$ +^tools/security/xensec_tool$ ^tools/tests/blowfish\.bin$ ^tools/tests/blowfish\.h$ ^tools/tests/test_x86_emulator$ diff -r 12be90e2f831 -r 4ffca478e2f7 Config.mk --- a/Config.mk Thu Sep 06 09:05:26 2007 -0600 +++ b/Config.mk Thu Sep 06 12:05:15 2007 -0600 @@ -20,6 +20,9 @@ HOSTCC = gcc HOSTCC = gcc HOSTCFLAGS = -Wall -Werror -Wstrict-prototypes -O2 -fomit-frame-pointer HOSTCFLAGS += -fno-strict-aliasing +HOSTCFLAGS_x86_32 = -m32 +HOSTCFLAGS_x86_64 = -m64 +HOSTCFLAGS += $(HOSTCFLAGS_$(XEN_COMPILE_ARCH)) DISTDIR ?= $(XEN_ROOT)/dist DESTDIR ?= / @@ -75,10 +78,10 @@ LDFLAGS += $(foreach i, $(EXTRA_LIB), -L LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i)) CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i)) -# If ACM_SECURITY = y, then the access control module is compiled -# into Xen and the policy type can be set by the boot policy file -# y - Build the Xen ACM framework -# n - Do not build the Xen ACM framework +# Enable XSM security module. Enabling XSM requires selection of an +# XSM security module (FLASK_ENABLE or ACM_SECURITY). +XSM_ENABLE ?= n +FLASK_ENABLE ?= n ACM_SECURITY ?= n # Optional components diff -r 12be90e2f831 -r 4ffca478e2f7 buildconfigs/mk.linux-2.6-xen --- a/buildconfigs/mk.linux-2.6-xen Thu Sep 06 09:05:26 2007 -0600 +++ b/buildconfigs/mk.linux-2.6-xen Thu Sep 06 12:05:15 2007 -0600 @@ -6,6 +6,16 @@ EXTRAVERSION ?= -xen # Linux search path, will be searched for tarballs and mercurial # repositories. LINUX_SRC_PATH ?= .:.. + +# The source directory is not automatically updated to avoid blowing +# away developer's changes. If you want to automatically pull a new +# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make +# command line. +ifeq ($(XEN_LINUX_UPDATE),y) +__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update +else +__XEN_LINUX_UPDATE = +endif XEN_LINUX_SOURCE ?= hg-clone @@ -115,6 +125,7 @@ endif echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT) \$$@"; \ ) > $(LINUX_DIR)/Makefile ; \ fi + $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) prepare .PHONY: prep prep: $(LINUX_DIR)/include/linux/autoconf.h @@ -137,3 +148,7 @@ mrproper: mrproper: rm -rf $(LINUX_SRCDIR) rm -f linux-$(LINUX_VER).tar.bz2 + +.PHONY: $(LINUX_SRCDIR)/.force-update +$(LINUX_SRCDIR)/.force-update: + @ : diff -r 12be90e2f831 -r 4ffca478e2f7 buildconfigs/src.hg-clone --- a/buildconfigs/src.hg-clone Thu Sep 06 09:05:26 2007 -0600 +++ b/buildconfigs/src.hg-clone Thu Sep 06 12:05:15 2007 -0600 @@ -5,16 +5,6 @@ LINUX_SRCDIR ?= linux-$(LINUX_VER)-xen.h # Repository to clone. XEN_LINUX_HGREPO ?= $$(sh buildconfigs/select-repository $(LINUX_SRCDIR) $(LINUX_SRC_PATH)) - -# The source directory is not automatically updated to avoid blowing -# away developer's changes. If you want to automatically pull a new -# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make -# command line. -ifeq ($(XEN_LINUX_UPDATE),y) -__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update -else -__XEN_LINUX_UPDATE = -endif # Set XEN_LINUX_HGREV to update to a particlar revision. XEN_LINUX_HGREV ?= tip @@ -40,7 +30,3 @@ XEN_LINUX_HGREV ?= tip ( cd $(LINUX_SRCDIR) && $(HG) update $(XEN_LINUX_HGREV) ); \ fi touch $@ - -.PHONY: $(LINUX_SRCDIR)/.force-update -$(LINUX_SRCDIR)/.force-update: - @ : diff -r 12be90e2f831 -r 4ffca478e2f7 buildconfigs/src.tarball --- a/buildconfigs/src.tarball Thu Sep 06 09:05:26 2007 -0600 +++ b/buildconfigs/src.tarball Thu Sep 06 12:05:15 2007 -0600 @@ -18,11 +18,11 @@ linux-%.tar.bz2: # XXX create a pristine tree for diff -Nurp convenience ifeq ($(XEN_LINUX_TARBALL_KETCHUP),y) -%/.valid-src: +%/.valid-src: $(__XEN_LINUX_UPDATE) $(KETCHUP) -d $(@D) $(LINUX_VER) touch $@ # update timestamp to avoid rebuild else -%/.valid-src: %.tar.bz2 +%/.valid-src: $(__XEN_LINUX_UPDATE) %.tar.bz2 rm -rf tmp-linux-$* $(@D) mkdir -p tmp-linux-$* tar -C tmp-linux-$* -jxf $< diff -r 12be90e2f831 -r 4ffca478e2f7 config/FreeBSD.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/FreeBSD.mk Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,1 @@ +include $(XEN_ROOT)/config/StdGNU.mk diff -r 12be90e2f831 -r 4ffca478e2f7 config/x86_32.mk --- a/config/x86_32.mk Thu Sep 06 09:05:26 2007 -0600 +++ b/config/x86_32.mk Thu Sep 06 12:05:15 2007 -0600 @@ -11,8 +11,6 @@ LIBDIR := lib LIBDIR := lib # Use only if calling $(LD) directly. -ifeq ($(XEN_OS),OpenBSD) -LDFLAGS_DIRECT += -melf_i386_obsd -else -LDFLAGS_DIRECT += -melf_i386 -endif +LDFLAGS_DIRECT_OpenBSD = _obsd +LDFLAGS_DIRECT_FreeBSD = _fbsd +LDFLAGS_DIRECT += -melf_i386$(LDFLAGS_DIRECT_$(XEN_OS)) diff -r 12be90e2f831 -r 4ffca478e2f7 docs/misc/dump-core-format.txt --- a/docs/misc/dump-core-format.txt Thu Sep 06 09:05:26 2007 -0600 +++ b/docs/misc/dump-core-format.txt Thu Sep 06 12:05:15 2007 -0600 @@ -80,7 +80,10 @@ Currently the following sections are def gmfn: machine physical frame number The size of arrays is stored in xch_nr_pages member of header note descriptor in .note.Xen note section. - The entryies are stored in pfn-ascending order. + The entries are stored in pfn-ascending order. + The value, {~(uint64_t)0, ~(uint64_t)0}, means invalid + (pfn, gmfn) and the corresponding page has zero. There might + exist invalid (pfn, gmfn)'s at the end part of this array. This section must exist when the domain is non auto translated physmap mode. Currently x86 paravirtualized domain. @@ -94,6 +97,9 @@ Currently the following sections are def The size of arrays is stored in xch_nr_pages member of header note descriptor in .note.Xen note section. The entries are stored in ascending order. + The value, ~(uint64_t)0, means invalid pfn and the + corresponding page has zero. There might exist invalid + pfn's at the end part of this array. This section must exist when the domain is auto translated physmap mode. Currently x86 full virtualized domain and ia64 domain. @@ -225,6 +231,8 @@ Currently only (major, minor) = (0, 1) i (0, 1) update - .xen_p2m, .xen_pfn section + Invalid pfn/gmfn. +- .xen_p2m, .xen_pfn section Arrays must be in pfn ascending order for efficient looking up. - EI_CLASS member of elf header was changed to ELFCLASS64 independent of architecture. This is mainly for x86_32pae. diff -r 12be90e2f831 -r 4ffca478e2f7 tools/Makefile --- a/tools/Makefile Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -3,6 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk SUBDIRS-y := SUBDIRS-y += libxc +SUBDIRS-y += flask SUBDIRS-y += xenstore SUBDIRS-y += misc SUBDIRS-y += examples diff -r 12be90e2f831 -r 4ffca478e2f7 tools/Rules.mk --- a/tools/Rules.mk Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/Rules.mk Thu Sep 06 12:05:15 2007 -0600 @@ -49,6 +49,8 @@ mk-symlinks: ( cd xen/hvm && ln -sf ../../$(XEN_ROOT)/xen/include/public/hvm/*.h . ) mkdir -p xen/io ( cd xen/io && ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . ) + mkdir -p xen/xsm + ( cd xen/xsm && ln -sf ../../$(XEN_ROOT)/xen/include/public/xsm/*.h . ) mkdir -p xen/arch-x86 ( cd xen/arch-x86 && ln -sf ../../$(XEN_ROOT)/xen/include/public/arch-x86/*.h . ) mkdir -p xen/foreign diff -r 12be90e2f831 -r 4ffca478e2f7 tools/blktap/drivers/tapdisk.c --- a/tools/blktap/drivers/tapdisk.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/blktap/drivers/tapdisk.c Thu Sep 06 12:05:15 2007 -0600 @@ -863,11 +863,7 @@ int main(int argc, char *argv[]) ptr = fd_start; while (ptr != NULL) { s = ptr->s; - unmap_disk(s); - free(s->blkif); - free(s->ring_info); - free(s); close(ptr->tap_fd); ptr = ptr->next; } diff -r 12be90e2f831 -r 4ffca478e2f7 tools/examples/blktap --- a/tools/examples/blktap Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/examples/blktap Thu Sep 06 12:05:15 2007 -0600 @@ -7,6 +7,57 @@ dir=$(dirname "$0") . "$dir/block-common.sh" findCommand "$@" + +## +# check_blktap_sharing file mode +# +# Perform the sharing check for the given blktap and mode. +# +check_blktap_sharing() +{ + local file="$1" + local mode="$2" + + local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE" + for dom in $(xenstore-list "$base_path") + do + for dev in $(xenstore-list "$base_path/$dom") + do + params=$(xenstore_read "$base_path/$dom/$dev/params" | cut -d: -f2) + if [ "$file" = "$params" ] + then + + if [ "$mode" = 'w' ] + then + if ! same_vm "$dom" + then + echo 'guest' + return + fi + else + local m=$(xenstore_read "$base_path/$dom/$dev/mode") + m=$(canonicalise_mode "$m") + + if [ "$m" = 'w' ] + then + if ! same_vm "$dom" + then + echo 'guest' + return + fi + fi + fi + fi + done + done + + echo 'ok' +} + +FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id") +FRONTEND_UUID=$(xenstore_read "/local/domain/$FRONTEND_ID/vm") +mode=$(xenstore_read "$XENBUS_PATH/mode") +mode=$(canonicalise_mode "$mode") t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING') if [ -n "$t" ] @@ -18,7 +69,19 @@ then p=${p#*:} fi fi -file=$(readlink -f "$p") || ebusy "$p does not exist." +# some versions of readlink cannot be passed a regular file +if [ -L "$p" ]; then + file=$(readlink -f "$p") || ebusy "$p link does not exist." +else + [ -f "$p" ] || { ebusy "$p file does not exist." } + file="$p" +fi + +if [ "$mode" != '!' ] +then + result=$(check_blktap_sharing "$file" "$mode") + [ "$result" = 'ok' ] || ebusy "$file already in use by other domain" +fi if [ "$command" = 'add' ] then diff -r 12be90e2f831 -r 4ffca478e2f7 tools/examples/block --- a/tools/examples/block Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/examples/block Thu Sep 06 12:05:15 2007 -0600 @@ -14,32 +14,6 @@ expand_dev() { ;; esac echo -n $dev -} - - -## -# canonicalise_mode mode -# -# Takes the given mode, which may be r, w, ro, rw, w!, or rw!, or variations -# thereof, and canonicalises them to one of -# -# 'r': perform checks for a new read-only mount; -# 'w': perform checks for a read-write mount; or -# '!': perform no checks at all. -# -canonicalise_mode() -{ - local mode="$1" - - if ! expr index "$mode" 'w' >/dev/null - then - echo 'r' - elif ! expr index "$mode" '!' >/dev/null - then - echo 'w' - else - echo '!' - fi } @@ -123,22 +97,6 @@ check_sharing() done echo 'ok' -} - - -same_vm() -{ - local otherdom="$1" - # Note that othervm can be MISSING here, because Xend will be racing with - # the hotplug scripts -- the entries in /local/domain can be removed by - # Xend before the hotplug scripts have removed the entry in - # /local/domain/0/backend/. In this case, we want to pretend that the - # VM is the same as FRONTEND_UUID, because that way the 'sharing' will be - # allowed. - local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm" \ - "$FRONTEND_UUID") - - [ "$FRONTEND_UUID" = "$othervm" ] } diff -r 12be90e2f831 -r 4ffca478e2f7 tools/examples/block-common.sh --- a/tools/examples/block-common.sh Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/examples/block-common.sh Thu Sep 06 12:05:15 2007 -0600 @@ -71,3 +71,46 @@ write_dev() { success } + + +## +# canonicalise_mode mode +# +# Takes the given mode, which may be r, w, ro, rw, w!, or rw!, or variations +# thereof, and canonicalises them to one of +# +# 'r': perform checks for a new read-only mount; +# 'w': perform checks for a read-write mount; or +# '!': perform no checks at all. +# +canonicalise_mode() +{ + local mode="$1" + + if ! expr index "$mode" 'w' >/dev/null + then + echo 'r' + elif ! expr index "$mode" '!' >/dev/null + then + echo 'w' + else + echo '!' + fi +} + + +same_vm() +{ + local otherdom="$1" + # Note that othervm can be MISSING here, because Xend will be racing with + # the hotplug scripts -- the entries in /local/domain can be removed by + # Xend before the hotplug scripts have removed the entry in + # /local/domain/0/backend/. In this case, we want to pretend that the + # VM is the same as FRONTEND_UUID, because that way the 'sharing' will be + # allowed. + local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm" \ + "$FRONTEND_UUID") + + [ "$FRONTEND_UUID" = "$othervm" ] +} + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/examples/network-bridge --- a/tools/examples/network-bridge Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/examples/network-bridge Thu Sep 06 12:05:15 2007 -0600 @@ -259,7 +259,8 @@ add_to_bridge2() { fi done - if [ ${i} -eq ${maxtries} ] ; then echo '(link isnt in running state)' ; fi + if [ ${i} -eq ${maxtries} ] ; then echo -n '(link isnt in running state)' ; fi + echo add_to_bridge ${bridge} ${dev} } diff -r 12be90e2f831 -r 4ffca478e2f7 tools/firmware/hvmloader/smbios.c --- a/tools/firmware/hvmloader/smbios.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/firmware/hvmloader/smbios.c Thu Sep 06 12:05:15 2007 -0600 @@ -159,8 +159,7 @@ int int hvm_write_smbios_tables(void) { - uint8_t uuid[16]; /* ** This will break if xen_domain_handle_t is - not uint8_t[16]. ** */ + xen_domain_handle_t uuid; uint16_t xen_major_version, xen_minor_version; uint32_t xen_version; char xen_extra_version[XEN_EXTRAVERSION_LEN]; @@ -173,6 +172,7 @@ hvm_write_smbios_tables(void) unsigned tmp_len; /* length of next string to add */ hypercall_xen_version(XENVER_guest_handle, uuid); + BUILD_BUG_ON(sizeof(xen_domain_handle_t) != 16); /* xen_version major and minor */ xen_version = hypercall_xen_version(XENVER_version, NULL); diff -r 12be90e2f831 -r 4ffca478e2f7 tools/firmware/hvmloader/util.h --- a/tools/firmware/hvmloader/util.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/firmware/hvmloader/util.h Thu Sep 06 12:05:15 2007 -0600 @@ -17,6 +17,7 @@ extern void __bug(char *file, int line) extern void __bug(char *file, int line) __attribute__((noreturn)); #define BUG() __bug(__FILE__, __LINE__) #define BUG_ON(p) do { if (p) BUG(); } while (0) +#define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)])) /* I/O output */ void outb(uint16_t addr, uint8_t val); diff -r 12be90e2f831 -r 4ffca478e2f7 tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/firmware/rombios/rombios.c Thu Sep 06 12:05:15 2007 -0600 @@ -1057,7 +1057,7 @@ static char CVSID[] = "$Id: rombios.c,v #define UNSUPPORTED_FUNCTION 0x86 #define none 0 -#define MAX_SCAN_CODE 0x53 +#define MAX_SCAN_CODE 0x58 static struct { Bit16u normal; @@ -1149,7 +1149,12 @@ static struct { { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */ { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */ { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */ - { 0x5300, 0x532e, none, none, 0x20 } /* Del */ + { 0x5300, 0x532e, none, none, 0x20 }, /* Del */ + { none, none, none, none, none }, /* ??? */ + { none, none, none, none, none }, /* ??? */ + { none, none, none, none, none }, /* ??? */ + { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */ + { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ }; Bit8u @@ -4682,7 +4687,7 @@ int09_function(DI, SI, BP, SP, BX, DX, C default: if (scancode & 0x80) return; /* toss key releases ... */ if (scancode > MAX_SCAN_CODE) { - BX_INFO("KBD: int09h_handler(): unknown scancode read!\n"); + BX_INFO("KBD: int09h_handler(): unknown scancode (%x) read!\n", scancode); return; } if (shift_flags & 0x08) { /* ALT */ diff -r 12be90e2f831 -r 4ffca478e2f7 tools/flask/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/flask/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,26 @@ +XEN_ROOT = ../.. +include $(XEN_ROOT)/tools/Rules.mk + +SUBDIRS := +SUBDIRS += libflask +SUBDIRS += loadpolicy + +.PHONY: all +all: + @set -e; for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir $@; \ + done + +.PHONY: install +install: + @set -e; for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir $@; \ + done + +.PHONY: clean +clean: + @set -e; for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir $@; \ + done + + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/flask/libflask/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/flask/libflask/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,65 @@ +MAJOR = 1.0 +MINOR = 0 + +XEN_ROOT = ../../.. +include $(XEN_ROOT)/tools/Rules.mk + +XEN_LIBXC = $(XEN_ROOT)/tools/libxc + +SRCS := +SRCS += flask_op.c + +CFLAGS += -Werror +CFLAGS += -fno-strict-aliasing +CFLAGS += $(INCLUDES) -I./include -I$(XEN_LIBXC) + +# Get gcc to generate the dependencies for us. +CFLAGS += -Wp,-MD,.$(@F).d +LDFLAGS += -L. +DEPS = .*.d + +LIB_OBJS := $(patsubst %.c,%.o,$(SRCS)) +PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS)) + +LIB := libflask.a +LIB += libflask.so libflask.so.$(MAJOR) libflask.so.$(MAJOR).$(MINOR) + +.PHONY: all +all: build + +.PHONY: build +build: + $(MAKE) $(LIB) + +.PHONY: install +install: build + [ -d $(DESTDIR)/usr/$(LIBDIR) ] || $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR) + [ -d $(DESTDIR)/usr/include ] || $(INSTALL_DIR) $(DESTDIR)/usr/include + $(INSTALL_PROG) libflask.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR) + $(INSTALL_DATA) libflask.a $(DESTDIR)/usr/$(LIBDIR) + ln -sf libflask.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libflask.so.$(MAJOR) + ln -sf libflask.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libflask.so + $(INSTALL_DATA) include/flask_op.h $(DESTDIR)/usr/include + +.PHONY: TAGS +TAGS: + etags -t *.c *.h + +.PHONY: clean +clean: + rm -rf *.a *.so* *.o *.opic *.rpm $(LIB) *~ $(DEPS) xen + +# libflask + +libflask.a: $(LIB_OBJS) + $(AR) rc $@ $^ + +libflask.so: libflask.so.$(MAJOR) + ln -sf $< $@ +libflask.so.$(MAJOR): libflask.so.$(MAJOR).$(MINOR) + ln -sf $< $@ + +libflask.so.$(MAJOR).$(MINOR): $(PIC_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libflask.so.$(MAJOR) -shared -o $@ $^ + +-include $(DEPS) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/flask/libflask/flask_op.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/flask/libflask/flask_op.c Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,100 @@ +/* + * + * Authors: Michael LeMay, <mdlemay@xxxxxxxxxxxxxx> + * George Coker, <gscoker@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <sys/ioctl.h> + +#include <xc_private.h> + +#include <flask_op.h> + +int flask_load(int xc_handle, char *buf, int size) +{ + int err; + flask_op_t op; + + op.cmd = FLASK_LOAD; + op.buf = buf; + op.size = size; + + if ( (err = do_flask_op(xc_handle, &op)) != 0 ) + return err; + + return 0; +} + +int flask_context_to_sid(int xc_handle, char *buf, int size, uint32_t *sid) +{ + int err; + flask_op_t op; + + op.cmd = FLASK_CONTEXT_TO_SID; + op.buf = buf; + op.size = size; + + if ( (err = do_flask_op(xc_handle, &op)) != 0 ) + return err; + + sscanf(buf, "%u", sid); + + return 0; +} + +int flask_sid_to_context(int xc_handle, int sid, char *buf, int size) +{ + int err; + flask_op_t op; + + op.cmd = FLASK_SID_TO_CONTEXT; + op.buf = buf; + op.size = size; + + snprintf(buf, size, "%u", sid); + + if ( (err = do_flask_op(xc_handle, &op)) != 0 ) + return err; + + return 0; +} + +int do_flask_op(int xc_handle, flask_op_t *op) +{ + int ret = -1; + DECLARE_HYPERCALL; + + hypercall.op = __HYPERVISOR_xsm_op; + hypercall.arg[0] = (unsigned long)op; + + if ( mlock(op, sizeof(*op)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out; + } + + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) + { + if ( errno == EACCES ) + fprintf(stderr, "XSM operation failed!\n"); + } + + safe_munlock(op, sizeof(*op)); + + out: + return ret; +} + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/flask/libflask/include/flask_op.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/flask/libflask/include/flask_op.h Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,46 @@ +/* + * + * Authors: Michael LeMay, <mdlemay@xxxxxxxxxxxxxx> + * George Coker, <gscoker@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#ifndef __FLASK_OP_H +#define __FLASK_OP_H + +#define FLASK_LOAD 1 +#define FLASK_GETENFORCE 2 +#define FLASK_SETENFORCE 3 +#define FLASK_CONTEXT_TO_SID 4 +#define FLASK_SID_TO_CONTEXT 5 +#define FLASK_ACCESS 6 +#define FLASK_CREATE 7 +#define FLASK_RELABEL 8 +#define FLASK_USER 9 +#define FLASK_POLICYVERS 10 +#define FLASK_GETBOOL 11 +#define FLASK_SETBOOL 12 +#define FLASK_COMMITBOOLS 13 +#define FLASK_MLS 14 +#define FLASK_DISABLE 15 +#define FLASK_GETAVC_THRESHOLD 16 +#define FLASK_SETAVC_THRESHOLD 17 +#define FLASK_AVC_HASHSTATS 18 +#define FLASK_AVC_CACHESTATS 19 +#define FLASK_MEMBER 20 + +typedef struct flask_op { + int cmd; + int size; + char *buf; +} flask_op_t; + +int flask_load(int xc_handle, char *buf, int size); +int flask_context_to_sid(int xc_handle, char *buf, int size, u_int32_t *sid); +int flask_sid_to_context(int xc_handle, int sid, char *buf, int size); +int do_flask_op(int xc_handle, flask_op_t *op); + +#endif diff -r 12be90e2f831 -r 4ffca478e2f7 tools/flask/loadpolicy/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/flask/loadpolicy/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,61 @@ +XEN_ROOT=../../.. +include $(XEN_ROOT)/tools/Rules.mk +XEN_LIBXC = $(XEN_ROOT)/tools/libxc + +INSTALL = install +INSTALL_DATA = $(INSTALL) -m0644 +INSTALL_PROG = $(INSTALL) -m0755 +INSTALL_DIR = $(INSTALL) -d -m0755 + +LIBXC_ROOT = $(XEN_ROOT)/tools/libxc +LIBFLASK_ROOT = $(XEN_ROOT)/tools/flask/libflask + +PROFILE=#-pg +BASECFLAGS=-Wall -g -Werror +# Make gcc generate dependencies. +BASECFLAGS += -Wp,-MD,.$(@F).d +PROG_DEP = .*.d +BASECFLAGS+= $(PROFILE) +#BASECFLAGS+= -I$(XEN_ROOT)/tools +BASECFLAGS+= -I$(LIBXC_ROOT) +BASECFLAGS+= -I$(LIBFLASK_ROOT)/include +BASECFLAGS+= -I. + +CFLAGS += $(BASECFLAGS) +LDFLAGS += $(PROFILE) -L$(XEN_LIBXC) -L$(LIBFLASK_ROOT) +TESTDIR = testsuite/tmp +TESTFLAGS= -DTESTING +TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR) + +CLIENTS := flask-loadpolicy +CLIENTS_OBJS := $(patsubst flask-%,%.o,$(CLIENTS)) + +.PHONY: all +all: $(CLIENTS) + +$(CLIENTS): flask-%: %.o + $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lflask -lxenctrl -o $@ + +.PHONY: clean +clean: + rm -f *.o *.opic *.so + rm -f $(CLIENTS) + $(RM) $(PROG_DEP) + +.PHONY: print-dir +print-dir: + @echo -n tools/flask/loadpolicy: + +.PHONY: print-end +print-end: + @echo + +.PHONY: install +install: all + $(INSTALL_DIR) -p $(DESTDIR)/usr/sbin + $(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/sbin + +-include $(PROG_DEP) + +# never delete any intermediate files. +.SECONDARY: diff -r 12be90e2f831 -r 4ffca478e2f7 tools/flask/loadpolicy/loadpolicy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/flask/loadpolicy/loadpolicy.c Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,130 @@ +/* + * + * Authors: Michael LeMay, <mdlemay@xxxxxxxxxxxxxx> + * George Coker, <gscoker@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <xenctrl.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <string.h> +#include <unistd.h> + +#include <flask_op.h> + +#define USE_MMAP + +static void usage (int argCnt, const char *args[]) +{ + fprintf(stderr, "Usage: %s <policy.file>\n", args[0]); + exit(1); +} + +int main (int argCnt, const char *args[]) +{ + const char *polFName; + int polFd = 0; + void *polMem = NULL; + void *polMemCp = NULL; + struct stat info; + int ret; + int xch = 0; + + if (argCnt != 2) + usage(argCnt, args); + + polFName = args[1]; + polFd = open(polFName, O_RDONLY); + if ( polFd < 0 ) + { + fprintf(stderr, "Error occurred opening policy file '%s': %s\n", + polFName, strerror(errno)); + ret = -1; + goto cleanup; + } + + ret = stat(polFName, &info); + if ( ret < 0 ) + { + fprintf(stderr, "Error occurred retrieving information about" + "policy file '%s': %s\n", polFName, strerror(errno)); + goto cleanup; + } + + polMemCp = malloc(info.st_size); + +#ifdef USE_MMAP + polMem = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, polFd, 0); + if ( !polMem ) + { + fprintf(stderr, "Error occurred mapping policy file in memory: %s\n", + strerror(errno)); + ret = -1; + goto cleanup; + } + + xch = xc_interface_open(); + if ( xch < 0 ) + { + fprintf(stderr, "Unable to create interface to xenctrl: %s\n", + strerror(errno)); + ret = -1; + goto cleanup; + } + + memcpy(polMemCp, polMem, info.st_size); +#else + ret = read(polFd, polMemCp, info.st_size); + if ( ret < 0 ) + { + fprintf(stderr, "Unable to read new Flask policy file: %s\n", + strerror(errno)); + goto cleanup; + } + else + { + printf("Read %d bytes from policy file '%s'.\n", ret, polFName); + } +#endif + + ret = flask_load(xch, polMemCp, info.st_size); + if ( ret < 0 ) + { + errno = -ret; + fprintf(stderr, "Unable to load new Flask policy: %s\n", + strerror(errno)); + ret = -1; + goto cleanup; + } + else + { + printf("Successfully loaded policy.\n"); + } + +done: + if ( polMemCp ) + free(polMemCp); + if ( polMem ) + { + ret = munmap(polMem, info.st_size); + if ( ret < 0 ) + fprintf(stderr, "Unable to unmap policy memory: %s\n", strerror(errno)); + } + if ( polFd ) + close(polFd); + if ( xch ) + xc_interface_close(xch); + + return ret; + +cleanup: + goto done; +} diff -r 12be90e2f831 -r 4ffca478e2f7 tools/ioemu/Makefile.target --- a/tools/ioemu/Makefile.target Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/ioemu/Makefile.target Thu Sep 06 12:05:15 2007 -0600 @@ -197,7 +197,6 @@ LIBS+=-lm LIBS+=-lm LIBS+=-L../../libxc -lxenctrl -lxenguest LIBS+=-L../../xenstore -lxenstore -LIBS+=-lpthread ifndef CONFIG_USER_ONLY LIBS+=-lz endif diff -r 12be90e2f831 -r 4ffca478e2f7 tools/ioemu/hw/cirrus_vga.c --- a/tools/ioemu/hw/cirrus_vga.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/ioemu/hw/cirrus_vga.c Thu Sep 06 12:05:15 2007 -0600 @@ -2559,7 +2559,11 @@ static void *set_vram_mapping(unsigned l for (i = 0; i < nr_extents; i++) extent_start[i] = (begin + i * TARGET_PAGE_SIZE) >> TARGET_PAGE_BITS; - set_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start); + if (set_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start) < 0) { + fprintf(logfile, "Failed set_mm_mapping\n"); + free(extent_start); + return NULL; + } vram_pointer = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, @@ -2567,6 +2571,7 @@ static void *set_vram_mapping(unsigned l if (vram_pointer == NULL) { fprintf(logfile, "xc_map_foreign_batch vgaram returned error %d\n", errno); + free(extent_start); return NULL; } diff -r 12be90e2f831 -r 4ffca478e2f7 tools/ioemu/hw/ide.c --- a/tools/ioemu/hw/ide.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/ioemu/hw/ide.c Thu Sep 06 12:05:15 2007 -0600 @@ -1876,6 +1876,9 @@ static void ide_ioport_write(void *opaqu break; case 0xaa: /* read look-ahead enable */ case 0x55: /* read look-ahead disable */ + case 0x42: /* EN_AAM: enable Automatic Acoustic Mode */ + case 0xc2: /* DIS_AAM: disable Automatic Acoustic Mode */ + case 0x85: /* DIS_APM: disable APM */ s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); break; @@ -1914,8 +1917,15 @@ static void ide_ioport_write(void *opaqu s->status = READY_STAT; ide_set_irq(s); break; - case WIN_STANDBYNOW1: case WIN_IDLEIMMEDIATE: + case WIN_STANDBY: + case WIN_SETIDLE1: + case WIN_STANDBYNOW1: + case WIN_SLEEPNOW1: + case WIN_STANDBY2: + case WIN_SETIDLE2: + case WIN_STANDBYNOW2: + case WIN_SLEEPNOW2: s->status = READY_STAT; ide_set_irq(s); break; diff -r 12be90e2f831 -r 4ffca478e2f7 tools/ioemu/hw/tpm_tis.c --- a/tools/ioemu/hw/tpm_tis.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/ioemu/hw/tpm_tis.c Thu Sep 06 12:05:15 2007 -0600 @@ -154,16 +154,16 @@ static int has_channel_local_socket(tpmS #define NUM_TRANSPORTS 1 struct vTPM_transmit { - int (*open) (tpmState *s, uint32_t vtpm_instance); - int (*write) (tpmState *s, const tpmBuffer *); - int (*read) (tpmState *s, tpmBuffer *); - int (*close) (tpmState *s, int); + int (*open_fn) (tpmState *s, uint32_t vtpm_instance); + int (*write_fn) (tpmState *s, const tpmBuffer *); + int (*read_fn) (tpmState *s, tpmBuffer *); + int (*close_fn) (tpmState *s, int); int (*has_channel) (tpmState *s); } vTPMTransmit[NUM_TRANSPORTS] = { - { .open = create_local_socket, - .write = write_local_socket, - .read = read_local_socket, - .close = close_local_socket, + { .open_fn = create_local_socket, + .write_fn = write_local_socket, + .read_fn = read_local_socket, + .close_fn = close_local_socket, .has_channel = has_channel_local_socket, } }; @@ -200,7 +200,7 @@ static void open_vtpm_channel(tpmState * int idx; /* search a usable transmit layer */ for (idx = 0; idx < NUM_TRANSPORTS; idx++) { - if (1 == vTPMTransmit[idx].open(s, s->vtpm_instance)) { + if (1 == vTPMTransmit[idx].open_fn(s, s->vtpm_instance)) { /* found one */ s->Transmitlayer = idx; break; @@ -213,7 +213,7 @@ static void open_vtpm_channel(tpmState * */ static inline void close_vtpm_channel(tpmState *s, int force) { - if (1 == vTPMTransmit[s->Transmitlayer].close(s, force)) { + if (1 == vTPMTransmit[s->Transmitlayer].close_fn(s, force)) { s->Transmitlayer = -1; } } @@ -974,7 +974,7 @@ static int TPM_Send(tpmState *s, tpmBuff buffer->instance[0] &= 0x1f; buffer->instance[0] |= (locty << 5); - len = vTPMTransmit[s->Transmitlayer].write(s, buffer); + len = vTPMTransmit[s->Transmitlayer].write_fn(s, buffer); if (len < 0) { s->Transmitlayer = -1; } @@ -990,7 +990,7 @@ static int TPM_Receive(tpmState *s, tpmB { int off; - off = vTPMTransmit[s->Transmitlayer].read(s, buffer); + off = vTPMTransmit[s->Transmitlayer].read_fn(s, buffer); if (off < 0) { /* EAGAIN is set in errno due to non-blocking mode */ diff -r 12be90e2f831 -r 4ffca478e2f7 tools/ioemu/target-i386-dm/exec-dm.c --- a/tools/ioemu/target-i386-dm/exec-dm.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/ioemu/target-i386-dm/exec-dm.c Thu Sep 06 12:05:15 2007 -0600 @@ -125,17 +125,10 @@ FILE *logfile; FILE *logfile; int loglevel; -#ifdef MAPCACHE -pthread_mutex_t mapcache_mutex; -#endif - void cpu_exec_init(CPUState *env) { CPUState **penv; int cpu_index; -#ifdef MAPCACHE - pthread_mutexattr_t mxattr; -#endif env->next_cpu = NULL; penv = &first_cpu; @@ -149,14 +142,6 @@ void cpu_exec_init(CPUState *env) /* alloc dirty bits array */ phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS); - -#ifdef MAPCACHE - /* setup memory access mutex to protect mapcache */ - pthread_mutexattr_init(&mxattr); - pthread_mutexattr_settype(&mxattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&mapcache_mutex, &mxattr); - pthread_mutexattr_destroy(&mxattr); -#endif } /* enable or disable low levels log */ @@ -470,6 +455,12 @@ static void memcpy_words(void *dst, void #else static void memcpy_words(void *dst, void *src, size_t n) { + /* Some architectures do not like unaligned accesses. */ + if (((unsigned long)dst | (unsigned long)src) & 3) { + memcpy(dst, src, n); + return; + } + while (n >= sizeof(uint32_t)) { *((uint32_t *)dst) = *((uint32_t *)src); dst = ((uint32_t *)dst) + 1; diff -r 12be90e2f831 -r 4ffca478e2f7 tools/ioemu/vl.h --- a/tools/ioemu/vl.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/ioemu/vl.h Thu Sep 06 12:05:15 2007 -0600 @@ -160,25 +160,15 @@ extern FILE *logfile; #if defined(__i386__) || defined(__x86_64__) - #define MAPCACHE - uint8_t *qemu_map_cache(target_phys_addr_t phys_addr); void qemu_invalidate_map_cache(void); - -#include <pthread.h> -extern pthread_mutex_t mapcache_mutex; -#define mapcache_lock() pthread_mutex_lock(&mapcache_mutex) -#define mapcache_unlock() pthread_mutex_unlock(&mapcache_mutex) - #else - #define qemu_invalidate_map_cache() ((void)0) +#endif #define mapcache_lock() ((void)0) #define mapcache_unlock() ((void)0) - -#endif extern int xc_handle; extern int domid; diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_acm.c --- a/tools/libxc/xc_acm.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_acm.c Thu Sep 06 12:05:15 2007 -0600 @@ -81,7 +81,7 @@ int xc_acm_op(int xc_handle, int cmd, vo acmctl.cmd = cmd; acmctl.interface_version = ACM_INTERFACE_VERSION; - hypercall.op = __HYPERVISOR_acm_op; + hypercall.op = __HYPERVISOR_xsm_op; hypercall.arg[0] = (unsigned long)&acmctl; if ( lock_pages(&acmctl, sizeof(acmctl)) != 0) { diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core.c Thu Sep 06 12:05:15 2007 -0600 @@ -17,8 +17,8 @@ * | .xen_prstatus | * | .xen_ia64_mmapped_regs if ia64 | * | .xen_shared_info if present | + * | .xen_pages | * | .xen_p2m or .xen_pfn | - * | .xen_pages | * +--------------------------------------------------------+ * |.note.Xen:note section | * | "Xen" is used as note name, | @@ -37,12 +37,12 @@ * +--------------------------------------------------------+ * |.xen_shared_info if possible | * +--------------------------------------------------------+ + * |.xen_pages | + * | page * nr_pages | + * +--------------------------------------------------------+ * |.xen_p2m or .xen_pfn | * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] | * | .xen_pfn: uint64_t[nr_pages] | - * +--------------------------------------------------------+ - * |.xen_pages | - * | page * nr_pages | * +--------------------------------------------------------+ * |.shstrtab: section header string table | * +--------------------------------------------------------+ @@ -57,21 +57,6 @@ /* number of pages to write at a time */ #define DUMP_INCREMENT (4 * 1024) - -static int -copy_from_domain_page(int xc_handle, - uint32_t domid, - unsigned long mfn, - void *dst_page) -{ - void *vaddr = xc_map_foreign_range( - xc_handle, domid, PAGE_SIZE, PROT_READ, mfn); - if ( vaddr == NULL ) - return -1; - memcpy(dst_page, vaddr, PAGE_SIZE); - munmap(vaddr, PAGE_SIZE); - return 0; -} /* string table */ struct xc_core_strtab { @@ -231,6 +216,35 @@ xc_core_shdr_set(Elf64_Shdr *shdr, return 0; } +static void +xc_core_ehdr_init(Elf64_Ehdr *ehdr) +{ + memset(ehdr, 0, sizeof(*ehdr)); + ehdr->e_ident[EI_MAG0] = ELFMAG0; + ehdr->e_ident[EI_MAG1] = ELFMAG1; + ehdr->e_ident[EI_MAG2] = ELFMAG2; + ehdr->e_ident[EI_MAG3] = ELFMAG3; + ehdr->e_ident[EI_CLASS] = ELFCLASS64; + ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA; + ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; + ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT; + + ehdr->e_type = ET_CORE; + ehdr->e_machine = ELF_ARCH_MACHINE; + ehdr->e_version = EV_CURRENT; + ehdr->e_entry = 0; + ehdr->e_phoff = 0; + ehdr->e_shoff = sizeof(*ehdr); + ehdr->e_flags = ELF_CORE_EFLAGS; + ehdr->e_ehsize = sizeof(*ehdr); + ehdr->e_phentsize = sizeof(Elf64_Phdr); + ehdr->e_phnum = 0; + ehdr->e_shentsize = sizeof(Elf64_Shdr); + /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet. + * fill it later */ +} + static int elfnote_fill_xen_version(int xc_handle, struct xen_dumpcore_elfnote_xen_version_desc @@ -277,12 +291,100 @@ elfnote_fill_xen_version(int xc_handle, return 0; } -static int +static void elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc *format_version) { format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT; - return 0; +} + +static void +elfnote_init(struct elfnote *elfnote) +{ + /* elf note section */ + memset(elfnote, 0, sizeof(*elfnote)); + elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1; + strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name)); +} + +static int +elfnote_dump_none(void *args, dumpcore_rtn_t dump_rtn) +{ + int sts; + struct elfnote elfnote; + struct xen_dumpcore_elfnote_none_desc none; + + elfnote_init(&elfnote); + memset(&none, 0, sizeof(none)); + + elfnote.descsz = sizeof(none); + elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE; + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + return sts; + return dump_rtn(args, (char*)&none, sizeof(none)); +} + +static int +elfnote_dump_core_header( + void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info, + int nr_vcpus, unsigned long nr_pages) +{ + int sts; + struct elfnote elfnote; + struct xen_dumpcore_elfnote_header_desc header; + + elfnote_init(&elfnote); + memset(&header, 0, sizeof(header)); + + elfnote.descsz = sizeof(header); + elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER; + header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC; + header.xch_nr_vcpus = nr_vcpus; + header.xch_nr_pages = nr_pages; + header.xch_page_size = PAGE_SIZE; + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + return sts; + return dump_rtn(args, (char*)&header, sizeof(header)); +} + +static int +elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle) +{ + int sts; + struct elfnote elfnote; + struct xen_dumpcore_elfnote_xen_version_desc xen_version; + + elfnote_init(&elfnote); + memset(&xen_version, 0, sizeof(xen_version)); + + elfnote.descsz = sizeof(xen_version); + elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION; + elfnote_fill_xen_version(xc_handle, &xen_version); + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + return sts; + return dump_rtn(args, (char*)&xen_version, sizeof(xen_version)); +} + +static int +elfnote_dump_format_version(void *args, dumpcore_rtn_t dump_rtn) +{ + int sts; + struct elfnote elfnote; + struct xen_dumpcore_elfnote_format_version_desc format_version; + + elfnote_init(&elfnote); + memset(&format_version, 0, sizeof(format_version)); + + elfnote.descsz = sizeof(format_version); + elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION; + elfnote_fill_format_version(&format_version); + sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); + if ( sts != 0 ) + return sts; + return dump_rtn(args, (char*)&format_version, sizeof(format_version)); } int @@ -327,13 +429,6 @@ xc_domain_dumpcore_via_callback(int xc_h struct xc_core_section_headers *sheaders = NULL; Elf64_Shdr *shdr; - /* elf notes */ - struct elfnote elfnote; - struct xen_dumpcore_elfnote_none_desc none; - struct xen_dumpcore_elfnote_header_desc header; - struct xen_dumpcore_elfnote_xen_version_desc xen_version; - struct xen_dumpcore_elfnote_format_version_desc format_version; - xc_core_arch_context_init(&arch_ctxt); if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL ) { @@ -379,8 +474,9 @@ xc_domain_dumpcore_via_callback(int xc_h } /* obtain memory map */ - sts = xc_core_arch_memory_map_get(xc_handle, &info, live_shinfo, - &memory_map, &nr_memory_map); + sts = xc_core_arch_memory_map_get(xc_handle, &arch_ctxt, &info, + live_shinfo, &memory_map, + &nr_memory_map); if ( sts != 0 ) goto out; @@ -410,70 +506,8 @@ xc_domain_dumpcore_via_callback(int xc_h } } - /* create .xen_p2m or .xen_pfn */ - j = 0; - for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ ) - { - uint64_t pfn_start; - uint64_t pfn_end; - - pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT; - pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT); - for ( i = pfn_start; i < pfn_end; i++ ) - { - if ( !auto_translated_physmap ) - { - if ( p2m[i] == INVALID_P2M_ENTRY ) - continue; - p2m_array[j].pfn = i; - p2m_array[j].gmfn = p2m[i]; - } - else - { - /* try to map page to determin wheter it has underlying page */ - void *vaddr = xc_map_foreign_range(xc_handle, domid, - PAGE_SIZE, PROT_READ, i); - if ( vaddr == NULL ) - continue; - munmap(vaddr, PAGE_SIZE); - pfn_array[j] = i; - } - - j++; - } - } - if ( j != nr_pages ) - { - PERROR("j (%ld) != nr_pages (%ld)", j , nr_pages); - /* When live dump-mode (-L option) is specified, - * guest domain may change its mapping. - */ - nr_pages = j; - } - - memset(&ehdr, 0, sizeof(ehdr)); - ehdr.e_ident[EI_MAG0] = ELFMAG0; - ehdr.e_ident[EI_MAG1] = ELFMAG1; - ehdr.e_ident[EI_MAG2] = ELFMAG2; - ehdr.e_ident[EI_MAG3] = ELFMAG3; - ehdr.e_ident[EI_CLASS] = ELFCLASS64; - ehdr.e_ident[EI_DATA] = ELF_ARCH_DATA; - ehdr.e_ident[EI_VERSION] = EV_CURRENT; - ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV; - ehdr.e_ident[EI_ABIVERSION] = EV_CURRENT; - - ehdr.e_type = ET_CORE; - ehdr.e_machine = ELF_ARCH_MACHINE; - ehdr.e_version = EV_CURRENT; - ehdr.e_entry = 0; - ehdr.e_phoff = 0; - ehdr.e_shoff = sizeof(ehdr); - ehdr.e_flags = ELF_CORE_EFLAGS; - ehdr.e_ehsize = sizeof(ehdr); - ehdr.e_phentsize = sizeof(Elf64_Phdr); - ehdr.e_phnum = 0; - ehdr.e_shentsize = sizeof(Elf64_Shdr); /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/ + xc_core_ehdr_init(&ehdr); /* create section header */ strtab = xc_core_strtab_init(); @@ -549,7 +583,7 @@ xc_domain_dumpcore_via_callback(int xc_h /* arch context */ sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab, &filesz, offset); - if ( sts != 0) + if ( sts != 0 ) goto out; offset += filesz; @@ -571,48 +605,12 @@ xc_domain_dumpcore_via_callback(int xc_h offset += filesz; } - /* p2m/pfn table */ - shdr = xc_core_shdr_get(sheaders); - if ( shdr == NULL ) - { - PERROR("Could not get section header for .xen_{p2m, pfn} table"); - goto out; - } - if ( !auto_translated_physmap ) - { - filesz = nr_pages * sizeof(p2m_array[0]); - sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M, - SHT_PROGBITS, - offset, filesz, __alignof__(p2m_array[0]), - sizeof(p2m_array[0])); - if ( sts != 0 ) - goto out; - } - else - { - filesz = nr_pages * sizeof(pfn_array[0]); - sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN, - SHT_PROGBITS, - offset, filesz, __alignof__(pfn_array[0]), - sizeof(pfn_array[0])); - if ( sts != 0 ) - goto out; - } - offset += filesz; - - /* pages */ - shdr = xc_core_shdr_get(sheaders); - if ( shdr == NULL ) - { - PERROR("could not get section headers for .xen_pages"); - goto out; - } - /* - * pages are the last section to allocate section headers + * pages and p2m/pfn are the last section to allocate section headers * so that we know the number of section headers here. + * 2 = pages section and p2m/pfn table section */ - fixup = sheaders->num * sizeof(*shdr); + fixup = (sheaders->num + 2) * sizeof(*shdr); /* zeroth section should have zero offset */ for ( i = 1; i < sheaders->num; i++ ) sheaders->shdrs[i].sh_offset += fixup; @@ -620,9 +618,43 @@ xc_domain_dumpcore_via_callback(int xc_h dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */ offset += dummy_len; + /* pages */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("could not get section headers for .xen_pages"); + goto out; + } filesz = nr_pages * PAGE_SIZE; sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS, offset, filesz, PAGE_SIZE, PAGE_SIZE); + if ( sts != 0 ) + goto out; + offset += filesz; + + /* p2m/pfn table */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for .xen_{p2m, pfn} table"); + goto out; + } + if ( !auto_translated_physmap ) + { + filesz = nr_pages * sizeof(p2m_array[0]); + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M, + SHT_PROGBITS, + offset, filesz, __alignof__(p2m_array[0]), + sizeof(p2m_array[0])); + } + else + { + filesz = nr_pages * sizeof(pfn_array[0]); + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN, + SHT_PROGBITS, + offset, filesz, __alignof__(pfn_array[0]), + sizeof(pfn_array[0])); + } if ( sts != 0 ) goto out; offset += filesz; @@ -645,54 +677,23 @@ xc_domain_dumpcore_via_callback(int xc_h if ( sts != 0 ) goto out; - /* elf note section */ - memset(&elfnote, 0, sizeof(elfnote)); - elfnote.namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1; - strncpy(elfnote.name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote.name)); - - /* elf note section:xen core header */ - elfnote.descsz = sizeof(none); - elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE; - sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); - if ( sts != 0 ) - goto out; - sts = dump_rtn(args, (char*)&none, sizeof(none)); - if ( sts != 0 ) - goto out; - - /* elf note section:xen core header */ - elfnote.descsz = sizeof(header); - elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER; - header.xch_magic = info.hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC; - header.xch_nr_vcpus = nr_vcpus; - header.xch_nr_pages = nr_pages; - header.xch_page_size = PAGE_SIZE; - sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); - if ( sts != 0 ) - goto out; - sts = dump_rtn(args, (char*)&header, sizeof(header)); + /* elf note section: xen core header */ + sts = elfnote_dump_none(args, dump_rtn); + if ( sts != 0 ) + goto out; + + /* elf note section: xen core header */ + sts = elfnote_dump_core_header(args, dump_rtn, &info, nr_vcpus, nr_pages); if ( sts != 0 ) goto out; /* elf note section: xen version */ - elfnote.descsz = sizeof(xen_version); - elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION; - elfnote_fill_xen_version(xc_handle, &xen_version); - sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); - if ( sts != 0 ) - goto out; - sts = dump_rtn(args, (char*)&xen_version, sizeof(xen_version)); + sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle); if ( sts != 0 ) goto out; /* elf note section: format version */ - elfnote.descsz = sizeof(format_version); - elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION; - elfnote_fill_format_version(&format_version); - sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote)); - if ( sts != 0 ) - goto out; - sts = dump_rtn(args, (char*)&format_version, sizeof(format_version)); + sts = elfnote_dump_format_version(args, dump_rtn); if ( sts != 0 ) goto out; @@ -714,16 +715,6 @@ xc_domain_dumpcore_via_callback(int xc_h if ( sts != 0 ) goto out; - /* p2m/pfn table: .xen_p2m/.xen_pfn */ - if ( !auto_translated_physmap ) - sts = dump_rtn(args, (char *)p2m_array, - sizeof(p2m_array[0]) * nr_pages); - else - sts = dump_rtn(args, (char *)pfn_array, - sizeof(pfn_array[0]) * nr_pages); - if ( sts != 0 ) - goto out; - /* Pad the output data to page alignment. */ memset(dummy, 0, PAGE_SIZE); sts = dump_rtn(args, dummy, dummy_len); @@ -731,24 +722,102 @@ xc_domain_dumpcore_via_callback(int xc_h goto out; /* dump pages: .xen_pages */ - for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ ) - { - uint64_t gmfn; - if ( !auto_translated_physmap ) - gmfn = p2m_array[i].gmfn; - else - gmfn = pfn_array[i]; - - copy_from_domain_page(xc_handle, domid, gmfn, dump_mem); - dump_mem += PAGE_SIZE; - if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) ) + j = 0; + dump_mem = dump_mem_start; + for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ ) + { + uint64_t pfn_start; + uint64_t pfn_end; + + pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT; + pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT); + for ( i = pfn_start; i < pfn_end; i++ ) { - sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start); + uint64_t gmfn; + void *vaddr; + + if ( j >= nr_pages ) + { + /* + * When live dump-mode (-L option) is specified, + * guest domain may increase memory. + */ + IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages); + goto copy_done; + } + + if ( !auto_translated_physmap ) + { + gmfn = p2m[i]; + if ( gmfn == INVALID_P2M_ENTRY ) + continue; + + p2m_array[j].pfn = i; + p2m_array[j].gmfn = gmfn; + } + else + { + if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) ) + continue; + + gmfn = i; + pfn_array[j] = i; + } + + vaddr = xc_map_foreign_range( + xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn); + if ( vaddr == NULL ) + continue; + memcpy(dump_mem, vaddr, PAGE_SIZE); + munmap(vaddr, PAGE_SIZE); + dump_mem += PAGE_SIZE; + if ( (j + 1) % DUMP_INCREMENT == 0 ) + { + sts = dump_rtn( + args, dump_mem_start, dump_mem - dump_mem_start); + if ( sts != 0 ) + goto out; + dump_mem = dump_mem_start; + } + + j++; + } + } + +copy_done: + sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start); + if ( sts != 0 ) + goto out; + if ( j < nr_pages ) + { + /* When live dump-mode (-L option) is specified, + * guest domain may reduce memory. pad with zero pages. + */ + IPRINTF("j (%ld) != nr_pages (%ld)", j , nr_pages); + memset(dump_mem_start, 0, PAGE_SIZE); + for (; j < nr_pages; j++) { + sts = dump_rtn(args, dump_mem_start, PAGE_SIZE); if ( sts != 0 ) goto out; - dump_mem = dump_mem_start; - } - } + if ( !auto_translated_physmap ) + { + p2m_array[j].pfn = XC_CORE_INVALID_PFN; + p2m_array[j].gmfn = XC_CORE_INVALID_GMFN; + } + else + pfn_array[j] = XC_CORE_INVALID_PFN; + } + } + + /* p2m/pfn table: .xen_p2m/.xen_pfn */ + if ( !auto_translated_physmap ) + sts = dump_rtn( + args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages); + else + sts = dump_rtn( + args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages); + if ( sts != 0 ) + goto out; /* elf section header string table: .shstrtab */ sts = dump_rtn(args, strtab->strings, strtab->current); @@ -758,6 +827,8 @@ xc_domain_dumpcore_via_callback(int xc_h sts = 0; out: + if ( memory_map != NULL ) + free(memory_map); if ( p2m != NULL ) munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES); if ( p2m_array != NULL ) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core.h --- a/tools/libxc/xc_core.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core.h Thu Sep 06 12:05:15 2007 -0600 @@ -107,6 +107,8 @@ struct xen_dumpcore_elfnote_format_versi struct xen_dumpcore_elfnote_format_version_desc format_version; }; +#define XC_CORE_INVALID_PFN (~(uint64_t)0) +#define XC_CORE_INVALID_GMFN (~(uint64_t)0) struct xen_dumpcore_p2m { uint64_t pfn; uint64_t gmfn; @@ -131,8 +133,10 @@ struct xc_core_memory_map { }; typedef struct xc_core_memory_map xc_core_memory_map_t; int xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info); -int xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, - shared_info_t *live_shinfo, +struct xc_core_arch_context; +int xc_core_arch_memory_map_get(int xc_handle, + struct xc_core_arch_context *arch_ctxt, + xc_dominfo_t *info, shared_info_t *live_shinfo, xc_core_memory_map_t **mapp, unsigned int *nr_entries); int xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core_ia64.c --- a/tools/libxc/xc_core_ia64.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core_ia64.c Thu Sep 06 12:05:15 2007 -0600 @@ -158,8 +158,8 @@ memory_map_get_old(int xc_handle, xc_dom } int -xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, - shared_info_t *live_shinfo, +xc_core_arch_memory_map_get(int xc_handle, struct xc_core_arch_context *unused, + xc_dominfo_t *info, shared_info_t *live_shinfo, xc_core_memory_map_t **mapp, unsigned int *nr_entries) { diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core_ia64.h --- a/tools/libxc/xc_core_ia64.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core_ia64.h Thu Sep 06 12:05:15 2007 -0600 @@ -46,6 +46,7 @@ int int xc_core_arch_context_dump(struct xc_core_arch_context* arch_ctxt, void* args, dumpcore_rtn_t dump_rtn); +#define xc_core_arch_gpfn_may_present(arch_ctxt, i) (1) #endif /* XC_CORE_IA64_H */ diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core_powerpc.c --- a/tools/libxc/xc_core_powerpc.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core_powerpc.c Thu Sep 06 12:05:15 2007 -0600 @@ -43,8 +43,8 @@ xc_core_arch_map_p2m(int xc_handle, xc_d } int -xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, - shared_info_t *live_shinfo, +xc_core_arch_memory_map_get(int xc_handle, struct xc_core_arch_context *unused, + xc_dominfo_t *info, shared_info_t *live_shinfo, xc_core_memory_map_t **mapp, unsigned int *nr_entries) { diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core_powerpc.h --- a/tools/libxc/xc_core_powerpc.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core_powerpc.h Thu Sep 06 12:05:15 2007 -0600 @@ -33,6 +33,7 @@ struct xc_core_arch_context { #define xc_core_arch_context_get(arch_ctxt, ctxt, xc_handle, domid) \ (0) #define xc_core_arch_context_dump(arch_ctxt, args, dump_rtn) (0) +#define xc_core_arch_gpfn_may_present(arch_ctxt, i) (1) static inline int xc_core_arch_context_get_shdr(struct xc_core_arch_context *arch_ctxt, diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core_x86.c --- a/tools/libxc/xc_core_x86.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core_x86.c Thu Sep 06 12:05:15 2007 -0600 @@ -33,8 +33,8 @@ xc_core_arch_auto_translated_physmap(con } int -xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, - shared_info_t *live_shinfo, +xc_core_arch_memory_map_get(int xc_handle, struct xc_core_arch_context *unused, + xc_dominfo_t *info, shared_info_t *live_shinfo, xc_core_memory_map_t **mapp, unsigned int *nr_entries) { diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_core_x86.h --- a/tools/libxc/xc_core_x86.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_core_x86.h Thu Sep 06 12:05:15 2007 -0600 @@ -40,6 +40,7 @@ struct xc_core_arch_context { #define xc_core_arch_context_get(arch_ctxt, ctxt, xc_handle, domid) \ (0) #define xc_core_arch_context_dump(arch_ctxt, args, dump_rtn) (0) +#define xc_core_arch_gpfn_may_present(arch_ctxt, i) (1) static inline int xc_core_arch_context_get_shdr(struct xc_core_arch_context *arch_ctxt, diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xc_domain.c Thu Sep 06 12:05:15 2007 -0600 @@ -55,10 +55,14 @@ int xc_domain_destroy(int xc_handle, int xc_domain_destroy(int xc_handle, uint32_t domid) { + int ret; DECLARE_DOMCTL; domctl.cmd = XEN_DOMCTL_destroydomain; domctl.domain = (domid_t)domid; - return do_domctl(xc_handle, &domctl); + do { + ret = do_domctl(xc_handle, &domctl); + } while ( ret && (errno == EAGAIN) ); + return ret; } int xc_domain_shutdown(int xc_handle, diff -r 12be90e2f831 -r 4ffca478e2f7 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/libxc/xenctrl.h Thu Sep 06 12:05:15 2007 -0600 @@ -26,8 +26,8 @@ #include <xen/event_channel.h> #include <xen/sched.h> #include <xen/memory.h> -#include <xen/acm.h> -#include <xen/acm_ops.h> +#include <xen/xsm/acm.h> +#include <xen/xsm/acm_ops.h> #ifdef __ia64__ #define XC_PAGE_SHIFT 14 diff -r 12be90e2f831 -r 4ffca478e2f7 tools/misc/xenperf.c --- a/tools/misc/xenperf.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/misc/xenperf.c Thu Sep 06 12:05:15 2007 -0600 @@ -46,7 +46,7 @@ const char *hypercall_name_table[64] = X(vcpu_op), X(set_segment_base), X(mmuext_op), - X(acm_op), + X(xsm_op), X(nmi_op), X(sched_op), X(callback_op), diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/Makefile --- a/tools/python/Makefile Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -1,5 +1,13 @@ XEN_ROOT = ../.. XEN_ROOT = ../.. include $(XEN_ROOT)/tools/Rules.mk + +XEN_SECURITY_MODULE = dummy +ifeq ($(FLASK_ENABLE),y) +XEN_SECURITY_MODULE = flask +endif +ifeq ($(ACM_SECURITY),y) +XEN_SECURITY_MODULE = acm +endif .PHONY: all all: build @@ -15,8 +23,8 @@ NLSDIR = /usr/share/locale NLSDIR = /usr/share/locale .PHONY: build buildpy -buildpy: - CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py build +buildpy: xsm.py + CC="$(CC)" CFLAGS="$(CFLAGS)" XEN_SECURITY_MODULE="$(XEN_SECURITY_MODULE)" python setup.py build build: buildpy refresh-pot refresh-po $(CATALOGS) @@ -53,6 +61,18 @@ refresh-po: $(POTFILE) %.mo: %.po $(MSGFMT) -c -o $@ $< +xsm.py: + @(set -e; \ + echo "XEN_SECURITY_MODULE = \""$(XEN_SECURITY_MODULE)"\""; \ + echo "from xsm_core import *"; \ + echo ""; \ + echo "import xen.util.xsm."$(XEN_SECURITY_MODULE)"."$(XEN_SECURITY_MODULE)" as xsm_module"; \ + echo ""; \ + echo "xsm_init(xsm_module)"; \ + echo "from xen.util.xsm."$(XEN_SECURITY_MODULE)"."$(XEN_SECURITY_MODULE)" import *"; \ + echo "del xsm_module"; \ + echo "") >xen/util/xsm/$@ + .PHONY: install ifndef XEN_PYTHON_NATIVE_INSTALL install: LIBPATH=$(shell PYTHONPATH=xen/util python -c "import auxbin; print auxbin.libpath()") @@ -84,4 +104,4 @@ test: .PHONY: clean clean: - rm -rf build *.pyc *.pyo *.o *.a *~ $(CATALOGS) + rm -rf build *.pyc *.pyo *.o *.a *~ $(CATALOGS) xen/util/xsm/xsm.py diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/setup.py --- a/tools/python/setup.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/setup.py Thu Sep 06 12:05:15 2007 -0600 @@ -44,6 +44,14 @@ acm = Extension("acm", libraries = libraries, sources = [ "xen/lowlevel/acm/acm.c" ]) +flask = Extension("flask", + extra_compile_args = extra_compile_args, + include_dirs = include_dirs + [ "xen/lowlevel/flask" ] + + [ "../flask/libflask/include" ], + library_dirs = library_dirs + [ "../flask/libflask" ], + libraries = libraries + [ "flask" ], + sources = [ "xen/lowlevel/flask/flask.c" ]) + ptsname = Extension("ptsname", extra_compile_args = extra_compile_args, include_dirs = include_dirs + [ "ptsname" ], @@ -51,7 +59,7 @@ ptsname = Extension("ptsname", libraries = libraries, sources = [ "ptsname/ptsname.c" ]) -modules = [ xc, xs, acm, ptsname ] +modules = [ xc, xs, ptsname, acm, flask ] if os.uname()[0] == 'SunOS': modules.append(scf) @@ -61,6 +69,10 @@ setup(name = 'xen', packages = ['xen', 'xen.lowlevel', 'xen.util', + 'xen.util.xsm', + 'xen.util.xsm.dummy', + 'xen.util.xsm.flask', + 'xen.util.xsm.acm', 'xen.xend', 'xen.xend.server', 'xen.xend.xenstore', diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/lowlevel/acm/acm.c --- a/tools/python/xen/lowlevel/acm/acm.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/lowlevel/acm/acm.c Thu Sep 06 12:05:15 2007 -0600 @@ -18,6 +18,7 @@ * * indent -i4 -kr -nut */ + #include <Python.h> #include <stdio.h> @@ -27,8 +28,8 @@ #include <stdlib.h> #include <sys/ioctl.h> #include <netinet/in.h> -#include <xen/acm.h> -#include <xen/acm_ops.h> +#include <xen/xsm/acm.h> +#include <xen/xsm/acm_ops.h> #include <xenctrl.h> diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/lowlevel/flask/flask.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/lowlevel/flask/flask.c Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,139 @@ +/****************************************************************************** + * flask.c + * + * Authors: George Coker, <gscoker@xxxxxxxxxxxxxx> + * Michael LeMay, <mdlemay@xxxxxxxxxxxxxx> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <Python.h> +#include <xenctrl.h> + +#include <flask_op.h> + +#define PKG "xen.lowlevel.flask" +#define CLS "flask" + +#define CTX_LEN 1024 + +static PyObject *xc_error_obj; + +typedef struct { + PyObject_HEAD; + int xc_handle; +} XcObject; + +static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args, + PyObject *kwds) +{ + int xc_handle; + char *ctx; + char *buf; + uint32_t len; + uint32_t sid; + int ret; + + static char *kwd_list[] = { "context", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, + &ctx) ) + return NULL; + + len = strlen(ctx); + + buf = malloc(len); + if (!buf) { + errno = -ENOMEM; + PyErr_SetFromErrno(xc_error_obj); + } + + memcpy(buf, ctx, len); + + xc_handle = xc_interface_open(); + if (xc_handle < 0) { + errno = xc_handle; + return PyErr_SetFromErrno(xc_error_obj); + } + + ret = flask_context_to_sid(xc_handle, buf, len, &sid); + + xc_interface_close(xc_handle); + + free(buf); + + if ( ret != 0 ) { + errno = -ret; + return PyErr_SetFromErrno(xc_error_obj); + } + + return PyInt_FromLong(sid); +} + +static PyObject *pyflask_sid_to_context(PyObject *self, PyObject *args, + PyObject *kwds) +{ + int xc_handle; + uint32_t sid; + char ctx[CTX_LEN]; + uint32_t ctx_len = CTX_LEN; + int ret; + + static char *kwd_list[] = { "sid", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, + &sid) ) + return NULL; + + xc_handle = xc_interface_open(); + if (xc_handle < 0) { + errno = xc_handle; + return PyErr_SetFromErrno(xc_error_obj); + } + + ret = flask_sid_to_context(xc_handle, sid, ctx, ctx_len); + + xc_interface_close(xc_handle); + + if ( ret != 0 ) { + errno = -ret; + return PyErr_SetFromErrno(xc_error_obj); + } + + return Py_BuildValue("s", ctx, ctx_len); +} + + +static PyMethodDef pyflask_methods[] = { + { "flask_context_to_sid", + (PyCFunction)pyflask_context_to_sid, + METH_KEYWORDS, "\n" + "Convert a context string to a dynamic SID.\n" + " context [str]: String specifying context to be converted\n" + "Returns: [int]: Numeric SID on success; -1 on error.\n" }, + + { "flask_sid_to_context", + (PyCFunction)pyflask_sid_to_context, + METH_KEYWORDS, "\n" + "Convert a dynamic SID to context string.\n" + " context [int]: SID to be converted\n" + "Returns: [str]: Numeric SID on success; -1 on error.\n" }, + + { NULL, NULL, 0, NULL } +}; + +PyMODINIT_FUNC initflask(void) +{ + Py_InitModule("flask", pyflask_methods); +} + + +/* + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * End: + */ diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/lowlevel/xc/xc.c Thu Sep 06 12:05:15 2007 -0600 @@ -685,7 +685,7 @@ static PyObject *pyxc_physinfo(XcObject char cpu_cap[128], *p=cpu_cap, *q=cpu_cap; int i, j, max_cpu_id; PyObject *ret_obj, *node_to_cpu_obj; - xc_cpu_to_node_t map[MAX_CPU_ID]; + xc_cpu_to_node_t map[MAX_CPU_ID + 1]; set_xen_guest_handle(info.cpu_to_node, map); info.max_cpu_id = MAX_CPU_ID; diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/acmpolicy.py --- a/tools/python/xen/util/acmpolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/util/acmpolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -1,4 +1,4 @@ -#============================================================================ + #============================================================================ # This library is free software; you can redistribute it and/or # modify it under the terms of version 2.1 of the GNU Lesser General Public # License as published by the Free Software Foundation. @@ -23,10 +23,11 @@ import array import array from xml.dom import minidom, Node from xen.xend.XendLogging import log -from xen.util import security, xsconstants, bootloader, mkdir +from xen.util import xsconstants, bootloader, mkdir from xen.util.xspolicy import XSPolicy -from xen.util.security import ACMError from xen.xend.XendError import SecurityError +import xen.util.xsm.acm.acm as security +from xen.util.xsm.xsm import XSMError ACM_POLICIES_DIR = security.policy_dir_prefix + "/" @@ -1240,8 +1241,8 @@ class ACMPolicy(XSPolicy): (major, minor) = self.getVersionTuple() hdr_bin = struct.pack(headerformat, + ACM_MAGIC, ACM_POLICY_VERSION, - ACM_MAGIC, totallen_bin, polref_offset, primpolcode, diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/security.py --- a/tools/python/xen/util/security.py Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1299 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 International Business Machines Corp. -# Author: Reiner Sailer -# Author: Bryan D. Payne <bdpayne@xxxxxxxxxx> -# Author: Stefan Berger <stefanb@xxxxxxxxxx> -#============================================================================ - -import commands -import logging -import os, string, re -import threading -import struct -import stat -from xen.lowlevel import acm -from xen.xend import sxp -from xen.xend import XendConstants -from xen.xend.XendLogging import log -from xen.xend.XendError import VmError -from xen.util import dictio, xsconstants -from xen.xend.XendConstants import * - -#global directories and tools for security management -policy_dir_prefix = "/etc/xen/acm-security/policies" -res_label_filename = policy_dir_prefix + "/resource_labels" -boot_filename = "/boot/grub/menu.lst" -altboot_filename = "/boot/grub/grub.conf" -xensec_xml2bin = "/usr/sbin/xensec_xml2bin" -xensec_tool = "/usr/sbin/xensec_tool" - -#global patterns for map file -#police_reference_tagname = "POLICYREFERENCENAME" -primary_entry_re = re.compile("\s*PRIMARY\s+.*", re.IGNORECASE) -secondary_entry_re = re.compile("\s*SECONDARY\s+.*", re.IGNORECASE) -label_template_re = re.compile(".*security_label_template.xml", re.IGNORECASE) -mapping_filename_re = re.compile(".*\.map", re.IGNORECASE) -policy_reference_entry_re = re.compile("\s*POLICYREFERENCENAME\s+.*", re.IGNORECASE) -vm_label_re = re.compile("\s*LABEL->SSID\s+VM\s+.*", re.IGNORECASE) -res_label_re = re.compile("\s*LABEL->SSID\s+RES\s+.*", re.IGNORECASE) -all_label_re = re.compile("\s*LABEL->SSID\s+.*", re.IGNORECASE) -access_control_re = re.compile("\s*access_control\s*=", re.IGNORECASE) - -#global patterns for boot configuration file -xen_title_re = re.compile("\s*title\s+XEN", re.IGNORECASE) -any_title_re = re.compile("\s*title\s", re.IGNORECASE) -xen_kernel_re = re.compile("\s*kernel.*xen.*\.gz", re.IGNORECASE) -kernel_ver_re = re.compile("\s*module.*vmlinuz", re.IGNORECASE) -any_module_re = re.compile("\s*module\s", re.IGNORECASE) -empty_line_re = re.compile("^\s*$") -binary_name_re = re.compile(".*[chwall|ste|chwall_ste].*\.bin", re.IGNORECASE) -policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE) - -#decision hooks known to the hypervisor -ACMHOOK_sharing = 1 -ACMHOOK_authorization = 2 - -#other global variables -NULL_SSIDREF = 0 - -#general Rlock for map files; only one lock for all mapfiles -__mapfile_lock = threading.RLock() -__resfile_lock = threading.RLock() - -log = logging.getLogger("xend.util.security") - -# Our own exception definition. It is masked (pass) if raised and -# whoever raises this exception must provide error information. -class ACMError(Exception): - def __init__(self,value): - self.value = value - def __str__(self): - return repr(self.value) - - - -def err(msg): - """Raise ACM exception. - """ - raise ACMError(msg) - - - -active_policy = None - - -def mapfile_lock(): - __mapfile_lock.acquire() - -def mapfile_unlock(): - __mapfile_lock.release() - - -def refresh_security_policy(): - """ - retrieves security policy - """ - global active_policy - - try: - active_policy = acm.policy() - except: - active_policy = "INACTIVE" - -# now set active_policy -refresh_security_policy() - -def on(): - """ - returns none if security policy is off (not compiled), - any string otherwise, use it: if not security.on() ... - """ - refresh_security_policy() - return (active_policy not in ['INACTIVE', 'NULL']) - - -def calc_dom_ssidref_from_info(info): - """ - Calculate a domain's ssidref from the security_label in its - info. - This function is called before the domain is started and - makes sure that: - - the type of the policy is the same as indicated in the label - - the name of the policy is the same as indicated in the label - - calculates an up-to-date ssidref for the domain - The latter is necessary since the domain's ssidref could have - changed due to changes to the policy. - """ - import xen.xend.XendConfig - if isinstance(info, xen.xend.XendConfig.XendConfig): - if info.has_key('security_label'): - seclab = info['security_label'] - tmp = seclab.split(":") - if len(tmp) != 3: - raise VmError("VM label '%s' in wrong format." % seclab) - typ, policyname, vmlabel = seclab.split(":") - if typ != xsconstants.ACM_POLICY_ID: - raise VmError("Policy type '%s' must be changed." % typ) - refresh_security_policy() - if active_policy != policyname: - raise VmError("Active policy '%s' different than " - "what in VM's label ('%s')." % - (active_policy, policyname)) - ssidref = label2ssidref(vmlabel, policyname, "dom") - return ssidref - else: - return 0x0 - raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'" - "not supported." % type(info)) - - -def getmapfile(policyname): - """ - in: if policyname is None then the currently - active hypervisor policy is used - out: 1. primary policy, 2. secondary policy, - 3. open file descriptor for mapping file, and - 4. True if policy file is available, False otherwise - """ - if not policyname: - policyname = active_policy - map_file_ok = False - primary = None - secondary = None - #strip last part of policy as file name part - policy_dir_list = string.split(policyname, ".") - policy_file = policy_dir_list.pop() - if len(policy_dir_list) > 0: - policy_dir = string.join(policy_dir_list, "/") + "/" - else: - policy_dir = "" - - map_filename = policy_dir_prefix + "/" + policy_dir + policy_file + ".map" - # check if it is there, if not check if policy file is there - if not os.path.isfile(map_filename): - policy_filename = policy_dir_prefix + "/" + policy_dir + policy_file + "-security_policy.xml" - if not os.path.isfile(policy_filename): - err("Policy file \'" + policy_filename + "\' not found.") - else: - err("Mapping file \'" + map_filename + "\' not found." + - " Use xm makepolicy to create it.") - - f = open(map_filename) - for line in f: - if policy_reference_entry_re.match(line): - l = line.split() - if (len(l) == 2) and (l[1] == policyname): - map_file_ok = True - elif primary_entry_re.match(line): - l = line.split() - if len(l) == 2: - primary = l[1] - elif secondary_entry_re.match(line): - l = line.split() - if len(l) == 2: - secondary = l[1] - f.close() - f = open(map_filename) - if map_file_ok and primary and secondary: - return (primary, secondary, f, True) - else: - err("Mapping file inconsistencies found. Try makepolicy to create a new one.") - - - -def ssidref2label(ssidref_var): - """ - returns labelname corresponding to ssidref; - maps current policy to default directory - to find mapping file - """ - #1. translated permitted input formats - if isinstance(ssidref_var, str): - ssidref_var.strip() - if ssidref_var[0:2] == "0x": - ssidref = int(ssidref_var[2:], 16) - else: - ssidref = int(ssidref_var) - elif isinstance(ssidref_var, int): - ssidref = ssidref_var - else: - err("Instance type of ssidref not supported (must be of type 'str' or 'int')") - - if ssidref == 0: - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - return ACM_LABEL_UNLABELED - - try: - mapfile_lock() - - (primary, secondary, f, pol_exists) = getmapfile(None) - if not f: - if (pol_exists): - err("Mapping file for policy not found.\n" + - "Please use makepolicy command to create mapping file!") - else: - err("Policy file for \'" + active_policy + "\' not found.") - - #2. get labelnames for both ssidref parts - pri_ssid = ssidref & 0xffff - sec_ssid = ssidref >> 16 - pri_null_ssid = NULL_SSIDREF & 0xffff - sec_null_ssid = NULL_SSIDREF >> 16 - pri_labels = [] - sec_labels = [] - labels = [] - - for line in f: - l = line.split() - if (len(l) < 5) or (l[0] != "LABEL->SSID"): - continue - if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid): - pri_labels.append(l[3]) - if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid): - sec_labels.append(l[3]) - f.close() - finally: - mapfile_unlock() - - #3. get the label that is in both lists (combination must be a single label) - if (primary == "CHWALL") and (pri_ssid == pri_null_ssid) and (sec_ssid != sec_null_ssid): - labels = sec_labels - elif (secondary == "CHWALL") and (pri_ssid != pri_null_ssid) and (sec_ssid == sec_null_ssid): - labels = pri_labels - elif secondary == "NULL": - labels = pri_labels - else: - for i in pri_labels: - for j in sec_labels: - if (i==j): - labels.append(i) - if len(labels) != 1: - err("Label for ssidref \'" + str(ssidref) + - "\' unknown or not unique in policy \'" + active_policy + "\'") - - return labels[0] - - - -def label2ssidref(labelname, policyname, typ): - """ - returns ssidref corresponding to labelname; - maps current policy to default directory - to find mapping file """ - - if policyname in ['NULL', 'INACTIVE', 'DEFAULT']: - err("Cannot translate labels for \'" + policyname + "\' policy.") - - allowed_types = ['ANY'] - if typ == 'dom': - allowed_types.append('VM') - elif typ == 'res': - allowed_types.append('RES') - else: - err("Invalid type. Must specify 'dom' or 'res'.") - - try: - mapfile_lock() - (primary, secondary, f, pol_exists) = getmapfile(policyname) - - #2. get labelnames for ssidref parts and find a common label - pri_ssid = [] - sec_ssid = [] - for line in f: - l = line.split() - if (len(l) < 5) or (l[0] != "LABEL->SSID"): - continue - if primary and (l[1] in allowed_types) and \ - (l[2] == primary) and \ - (l[3] == labelname): - pri_ssid.append(int(l[4], 16)) - if secondary and (l[1] in allowed_types) and \ - (l[2] == secondary) and \ - (l[3] == labelname): - sec_ssid.append(int(l[4], 16)) - f.close() - if (typ == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0): - pri_ssid.append(NULL_SSIDREF) - elif (typ == 'res') and (secondary == "CHWALL") and \ - (len(sec_ssid) == 0): - sec_ssid.append(NULL_SSIDREF) - - #3. sanity check and composition of ssidref - if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and \ - (secondary != "NULL")): - err("Label \'" + labelname + "\' not found.") - elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1): - err("Label \'" + labelname + "\' not unique in policy (policy error)") - if secondary == "NULL": - return pri_ssid[0] - else: - return (sec_ssid[0] << 16) | pri_ssid[0] - finally: - mapfile_unlock() - - -def refresh_ssidref(config): - """ - looks up ssidref from security field - and refreshes the value if label exists - """ - #called by dom0, policy could have changed after xen.utils.security was initialized - refresh_security_policy() - - security = None - if isinstance(config, dict): - security = config['security'] - elif isinstance(config, list): - security = sxp.child_value(config, 'security') - else: - err("Instance type of config parameter not supported.") - if not security: - #nothing to do (no security label attached) - return config - - policyname = None - labelname = None - # compose new security field - for idx in range(0, len(security)): - if security[idx][0] == 'ssidref': - security.pop(idx) - break - elif security[idx][0] == 'access_control': - for jdx in [1, 2]: - if security[idx][jdx][0] == 'label': - labelname = security[idx][jdx][1] - elif security[idx][jdx][0] == 'policy': - policyname = security[idx][jdx][1] - else: - err("Illegal field in access_control") - #verify policy is correct - if active_policy != policyname: - err("Policy \'" + str(policyname) + - "\' in label does not match active policy \'" - + str(active_policy) +"\'!") - - new_ssidref = label2ssidref(labelname, policyname, 'dom') - if not new_ssidref: - err("SSIDREF refresh failed!") - - security.append([ 'ssidref',str(new_ssidref)]) - security = ['security', security ] - - for idx in range(0,len(config)): - if config[idx][0] == 'security': - config.pop(idx) - break - config.append(security) - - - -def get_ssid(domain): - """ - enables domains to retrieve the label / ssidref of a running domain - """ - if not on(): - err("No policy active.") - - if isinstance(domain, str): - domain_int = int(domain) - elif isinstance(domain, int): - domain_int = domain - else: - err("Illegal parameter type.") - try: - ssid_info = acm.getssid(int(domain_int)) - except: - err("Cannot determine security information.") - - if active_policy in ["DEFAULT"]: - label = "DEFAULT" - else: - label = ssidref2label(ssid_info["ssidref"]) - return(ssid_info["policyreference"], - label, - ssid_info["policytype"], - ssid_info["ssidref"]) - - - -def get_decision(arg1, arg2): - """ - enables domains to retrieve access control decisions from - the hypervisor Access Control Module. - IN: args format = ['domid', id] or ['ssidref', ssidref] - or ['access_control', ['policy', policy], ['label', label], ['type', type]] - """ - - if not on(): - err("No policy active.") - - #translate labels before calling low-level function - if arg1[0] == 'access_control': - if (arg1[1][0] != 'policy') or (arg1[2][0] != 'label') or (arg1[3][0] != 'type'): - err("Argument type not supported.") - ssidref = label2ssidref(arg1[2][1], arg1[1][1], arg1[3][1]) - arg1 = ['ssidref', str(ssidref)] - if arg2[0] == 'access_control': - if (arg2[1][0] != 'policy') or (arg2[2][0] != 'label') or (arg2[3][0] != 'type'): - err("Argument type not supported.") - ssidref = label2ssidref(arg2[2][1], arg2[1][1], arg2[3][1]) - arg2 = ['ssidref', str(ssidref)] - - # accept only int or string types for domid and ssidref - if isinstance(arg1[1], int): - arg1[1] = str(arg1[1]) - if isinstance(arg2[1], int): - arg2[1] = str(arg2[1]) - if not isinstance(arg1[1], str) or not isinstance(arg2[1], str): - err("Invalid id or ssidref type, string or int required") - - try: - decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1], - ACMHOOK_sharing) - except: - err("Cannot determine decision.") - - if decision: - return decision - else: - err("Cannot determine decision (Invalid parameter).") - - -def has_authorization(ssidref): - """ Check if the domain with the given ssidref has authorization to - run on this system. To have authoriztion dom0's STE types must - be a superset of that of the domain's given through its ssidref. - """ - rc = True - dom0_ssidref = int(acm.getssid(0)['ssidref']) - decision = acm.getdecision('ssidref', str(dom0_ssidref), - 'ssidref', str(ssidref), - ACMHOOK_authorization) - if decision == "DENIED": - rc = False - return rc - - -def hv_chg_policy(bin_pol, del_array, chg_array): - """ - Change the binary policy in the hypervisor - The 'del_array' and 'chg_array' give hints about deleted ssidrefs - and changed ssidrefs which can be due to deleted VM labels - or reordered VM labels - """ - rc = -xsconstants.XSERR_GENERAL_FAILURE - errors = "" - if not on(): - err("No policy active.") - try: - rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array) - except Exception, e: - pass - if len(errors) > 0: - rc = -xsconstants.XSERR_HV_OP_FAILED - return rc, errors - - -def make_policy(policy_name): - policy_file = string.join(string.split(policy_name, "."), "/") - if not os.path.isfile(policy_dir_prefix + "/" + policy_file + "-security_policy.xml"): - err("Unknown policy \'" + policy_name + "\'") - - (ret, output) = commands.getstatusoutput(xensec_xml2bin + " -d " + policy_dir_prefix + " " + policy_file) - if ret: - err("Creating policy failed:\n" + output) - -def load_policy(policy_name): - global active_policy - policy_file = policy_dir_prefix + "/" + string.join(string.split(policy_name, "."), "/") - if not os.path.isfile(policy_file + ".bin"): - if os.path.isfile(policy_file + "-security_policy.xml"): - err("Binary file does not exist." + - "Please use makepolicy to build the policy binary.") - else: - err("Unknown Policy " + policy_name) - - #require this policy to be the first or the same as installed - if active_policy not in ['DEFAULT', policy_name]: - err("Active policy \'" + active_policy + - "\' incompatible with new policy \'" + policy_name + "\'") - (ret, output) = commands.getstatusoutput(xensec_tool + " loadpolicy " + policy_file + ".bin") - if ret: - err("Loading policy failed:\n" + output) - else: - # refresh active policy - refresh_security_policy() - - - -def dump_policy(): - if active_policy in ['NULL', 'INACTIVE']: - err("\'" + active_policy + "\' policy. Nothing to dump.") - - (ret, output) = commands.getstatusoutput(xensec_tool + " getpolicy") - if ret: - err("Dumping hypervisor policy failed:\n" + output) - print output - - - -def list_labels(policy_name, condition): - if (not policy_name) and (active_policy) in ["NULL", "INACTIVE", "DEFAULT"]: - err("Current policy \'" + active_policy + "\' has no labels defined.\n") - - (primary, secondary, f, pol_exists) = getmapfile(policy_name) - if not f: - if pol_exists: - err("Cannot find mapfile for policy \'" + policy_name + - "\'.\nPlease use makepolicy to create mapping file.") - else: - err("Unknown policy \'" + policy_name + "\'") - - labels = [] - for line in f: - if condition.match(line): - label = line.split()[3] - if label not in labels: - labels.append(label) - return labels - - -def get_res_label(resource): - """Returns resource label information (policytype, label, policy) if - it exists. Otherwise returns null label and policy. - """ - def default_res_label(): - ssidref = NULL_SSIDREF - if on(): - label = ssidref2label(ssidref) - else: - label = None - return (xsconstants.ACM_POLICY_ID, 'NULL', label) - - - tmp = get_resource_label(resource) - if len(tmp) == 2: - policytype = xsconstants.ACM_POLICY_ID - policy, label = tmp - elif len(tmp) == 3: - policytype, policy, label = tmp - else: - policytype, policy, label = default_res_label() - - return (policytype, label, policy) - - -def get_res_security_details(resource): - """Returns the (label, ssidref, policy) associated with a given - resource from the global resource label file. - """ - def default_security_details(): - ssidref = NULL_SSIDREF - if on(): - label = ssidref2label(ssidref) - else: - label = None - policy = active_policy - return (label, ssidref, policy) - - (label, ssidref, policy) = default_security_details() - - # find the entry associated with this resource - (policytype, label, policy) = get_res_label(resource) - if policy == 'NULL': - log.info("Resource label for "+resource+" not in file, using DEFAULT.") - return default_security_details() - - # is this resource label for the running policy? - if policy == active_policy: - ssidref = label2ssidref(label, policy, 'res') - else: - log.info("Resource label not for active policy, using DEFAULT.") - return default_security_details() - - return (label, ssidref, policy) - -def security_label_to_details(seclab): - """ Convert a Xen-API type of security label into details """ - def default_security_details(): - ssidref = NULL_SSIDREF - if on(): - label = ssidref2label(ssidref) - else: - label = None - policy = active_policy - return (label, ssidref, policy) - - (policytype, policy, label) = seclab.split(":") - - # is this resource label for the running policy? - if policy == active_policy: - ssidref = label2ssidref(label, policy, 'res') - else: - log.info("Resource label not for active policy, using DEFAULT.") - return default_security_details() - - return (label, ssidref, policy) - -def unify_resname(resource, mustexist=True): - """Makes all resource locations absolute. In case of physical - resources, '/dev/' is added to local file names""" - - if not resource: - return resource - - # sanity check on resource name - try: - (typ, resfile) = resource.split(":", 1) - except: - err("Resource spec '%s' contains no ':' delimiter" % resource) - - if typ == "tap": - try: - (subtype, resfile) = resfile.split(":") - except: - err("Resource spec '%s' contains no tap subtype" % resource) - - import os - if typ in ["phy", "tap"]: - if not resfile.startswith("/"): - resfile = "/dev/" + resfile - if mustexist: - stats = os.lstat(resfile) - if stat.S_ISLNK(stats[stat.ST_MODE]): - resolved = os.readlink(resfile) - if resolved[0] != "/": - resfile = os.path.join(os.path.dirname(resfile), resolved) - resfile = os.path.abspath(resfile) - else: - resfile = resolved - stats = os.lstat(resfile) - if not (stat.S_ISBLK(stats[stat.ST_MODE])): - err("Invalid resource") - - if typ in [ "file", "tap" ]: - if mustexist: - stats = os.lstat(resfile) - if stat.S_ISLNK(stats[stat.ST_MODE]): - resfile = os.readlink(resfile) - stats = os.lstat(resfile) - if not stat.S_ISREG(stats[stat.ST_MODE]): - err("Invalid resource") - - #file: resources must specified with absolute path - #vlan resources don't start with '/' - if typ != "vlan": - if (not resfile.startswith("/")) or \ - (mustexist and not os.path.exists(resfile)): - err("Invalid resource.") - - # from here on absolute file names with resources - if typ == "tap": - typ = typ + ":" + subtype - resource = typ + ":" + resfile - return resource - - -def res_security_check(resource, domain_label): - """Checks if the given resource can be used by the given domain - label. Returns 1 if the resource can be used, otherwise 0. - """ - rtnval = 1 - - # if security is on, ask the hypervisor for a decision - if on(): - #build canonical resource name - resource = unify_resname(resource) - - (label, ssidref, policy) = get_res_security_details(resource) - domac = ['access_control'] - domac.append(['policy', active_policy]) - domac.append(['label', domain_label]) - domac.append(['type', 'dom']) - decision = get_decision(domac, ['ssidref', str(ssidref)]) - - # provide descriptive error messages - if decision == 'DENIED': - if label == ssidref2label(NULL_SSIDREF): - raise ACMError("Resource '"+resource+"' is not labeled") - rtnval = 0 - else: - raise ACMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed") - rtnval = 0 - - # security is off, make sure resource isn't labeled - else: - # Note, we can't canonicalise the resource here, because people using - # xm without ACM are free to use relative paths. - (policytype, label, policy) = get_res_label(resource) - if policy != 'NULL': - raise ACMError("Security is off, but '"+resource+"' is labeled") - rtnval = 0 - - return rtnval - -def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label): - """Checks if the given resource can be used by the given domain - label. Returns 1 if the resource can be used, otherwise 0. - """ - rtnval = 1 - # if security is on, ask the hypervisor for a decision - if on(): - typ, dpolicy, domain_label = xapi_dom_label.split(":") - if not dpolicy or not domain_label: - raise VmError("VM security label in wrong format.") - if active_policy != rpolicy: - raise VmError("Resource's policy '%s' != active policy '%s'" % - (rpolicy, active_policy)) - domac = ['access_control'] - domac.append(['policy', active_policy]) - domac.append(['label', domain_label]) - domac.append(['type', 'dom']) - decision = get_decision(domac, ['ssidref', str(rssidref)]) - - log.info("Access Control Decision : %s" % decision) - # provide descriptive error messages - if decision == 'DENIED': - if rlabel == ssidref2label(NULL_SSIDREF): - #raise ACMError("Resource is not labeled") - rtnval = 0 - else: - #raise ACMError("Permission denied for resource because label '"+rlabel+"' is not allowed") - rtnval = 0 - - # security is off, make sure resource isn't labeled - else: - # Note, we can't canonicalise the resource here, because people using - # xm without ACM are free to use relative paths. - if rpolicy != 'NULL': - #raise ACMError("Security is off, but resource is labeled") - rtnval = 0 - - return rtnval - - -def validate_label(label, policyref): - """ - Make sure that this label is part of the currently enforced policy - and that it reference the current policy. - """ - rc = xsconstants.XSERR_SUCCESS - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - curpol = XSPolicyAdminInstance().get_loaded_policy() - if not curpol or curpol.get_name() != policyref: - rc = -xsconstants.XSERR_BAD_LABEL - else: - try: - label2ssidref(label, curpol.get_name() , 'res') - except: - rc = -xsconstants.XSERR_BAD_LABEL - return rc - - -def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi): - """Assign a resource label to a resource - @param resource: The name of a resource, i.e., "phy:/dev/hda", or - "tap:qcow:/path/to/file.qcow" - - @param reslabel_xapi: A resource label foramtted as in all other parts of - the Xen-API, i.e., ACM:xm-test:blue" - @rtype: int - @return Success (0) or failure value (< 0) - """ - olabel = "" - if reslabel_xapi == "": - return rm_resource_label(resource, oldlabel_xapi) - typ, policyref, label = reslabel_xapi.split(":") - if typ != xsconstants.ACM_POLICY_ID: - return -xsconstants.XSERR_WRONG_POLICY_TYPE - if not policyref or not label: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - if oldlabel_xapi not in [ "" ]: - tmp = oldlabel_xapi.split(":") - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - otyp, opolicyref, olabel = tmp - # Only ACM is supported - if otyp != xsconstants.ACM_POLICY_ID and \ - otyp != xsconstants.INVALID_POLICY_PREFIX + \ - xsconstants.ACM_POLICY_ID: - return -xsconstants.XSERR_WRONG_POLICY_TYPE - rc = validate_label(label, policyref) - if rc != xsconstants.XSERR_SUCCESS: - return rc - return set_resource_label(resource, typ, policyref, label, olabel) - - -def is_resource_in_use(resource): - """ - Domain-0 'owns' resources of type 'VLAN', the rest are owned by - the guests. - """ - from xen.xend import XendDomain - lst = [] - if resource.startswith('vlan'): - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - curpol = XSPolicyAdminInstance().get_loaded_policy() - policytype, label, policy = get_res_label(resource) - if curpol and \ - policytype == xsconstants.ACM_POLICY_ID and \ - policy == curpol.get_name() and \ - label in curpol.policy_get_resourcelabel_names(): - # VLAN is in use. - lst.append(XendDomain.instance(). - get_vm_by_uuid(XendDomain.DOM0_UUID)) - else: - dominfos = XendDomain.instance().list('all') - for dominfo in dominfos: - if is_resource_in_use_by_dom(dominfo, resource): - lst.append(dominfo) - return lst - -def devices_equal(res1, res2, mustexist=True): - """ Determine whether two devices are equal """ - return (unify_resname(res1, mustexist) == - unify_resname(res2, mustexist)) - -def is_resource_in_use_by_dom(dominfo, resource): - """ Determine whether a resources is in use by a given domain - @return True or False - """ - if not dominfo.domid: - return False - if dominfo._stateGet() not in [ DOM_STATE_RUNNING ]: - return False - devs = dominfo.info['devices'] - uuids = devs.keys() - for uuid in uuids: - dev = devs[uuid] - if len(dev) >= 2 and dev[1].has_key('uname'): - # dev[0] is type, i.e. 'vbd' - if devices_equal(dev[1]['uname'], resource, mustexist=False): - log.info("RESOURCE IN USE: Domain %d uses %s." % - (dominfo.domid, resource)) - return True - return False - - -def get_domain_resources(dominfo): - """ Collect all resources of a domain in a map where each entry of - the map is a list. - Entries are strored in the following formats: - tap:qcow:/path/xyz.qcow - """ - resources = { 'vbd' : [], 'tap' : [], 'vif' : []} - devs = dominfo.info['devices'] - uuids = devs.keys() - for uuid in uuids: - dev = devs[uuid] - typ = dev[0] - if typ in [ 'vbd', 'tap' ]: - resources[typ].append(dev[1]['uname']) - if typ in [ 'vif' ]: - sec_lab = dev[1].get('security_label') - if sec_lab: - resources[typ].append(sec_lab) - else: - # !!! This should really get the label of the domain - # or at least a resource label that has the same STE type - # as the domain has - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - resources[typ].append("%s:%s:%s" % - (xsconstants.ACM_POLICY_ID, - active_policy, - ACM_LABEL_UNLABELED)) - - return resources - - -def resources_compatible_with_vmlabel(xspol, dominfo, vmlabel): - """ - Check whether the resources' labels are compatible with the - given VM label. This is a function to be used when for example - a running domain is to get the new label 'vmlabel' - """ - if not xspol: - return False - - try: - __resfile_lock.acquire() - try: - access_control = dictio.dict_read("resources", - res_label_filename) - except: - return False - return __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel, - access_control) - finally: - __resfile_lock.release() - return False - - -def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel, - access_control, - is_policy_update=False): - """ - Check whether the resources' labels are compatible with the - given VM label. The access_control parameter provides a - dictionary of the resource name to resource label mappings - under which the evaluation should be done. - """ - def collect_labels(reslabels, s_label, polname): - if len(s_label) != 3 or polname != s_label[1]: - return False - label = s_label[2] - if not label in reslabels: - reslabels.append(label) - return True - - resources = get_domain_resources(dominfo) - reslabels = [] # all resource labels - - polname = xspol.get_name() - for key, value in resources.items(): - if key in [ 'vbd', 'tap' ]: - for res in resources[key]: - try: - label = access_control[res] - if not collect_labels(reslabels, label, polname): - return False - except: - return False - elif key in [ 'vif' ]: - for xapi_label in value: - label = xapi_label.split(":") - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - if not (is_policy_update and \ - label[2] == ACM_LABEL_UNLABELED): - if not collect_labels(reslabels, label, polname): - return False - else: - log.error("Unhandled device type: %s" % key) - return False - - # Check that all resource labes have a common STE type with the - # vmlabel - if len(reslabels) > 0: - rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels) - else: - rc = True - log.info("vmlabel=%s, reslabels=%s, rc=%s" % - (vmlabel, reslabels, str(rc))) - return rc; - -def set_resource_label(resource, policytype, policyref, reslabel, \ - oreslabel = None): - """Assign a label to a resource - If the old label (oreslabel) is given, then the resource must have - that old label. - A resource label may be changed if - - the resource is not in use - @param resource : The name of a resource, i.e., "phy:/dev/hda" - @param policyref : The name of the policy - @param reslabel : the resource label within the policy - @param oreslabel : optional current resource label - - @rtype: int - @return Success (0) or failure value (< 0) - """ - try: - resource = unify_resname(resource, mustexist=False) - except Exception: - return -xsconstants.XSERR_BAD_RESOURCE_FORMAT - - domains = is_resource_in_use(resource) - if len(domains) > 0: - return -xsconstants.XSERR_RESOURCE_IN_USE - - try: - __resfile_lock.acquire() - access_control = {} - try: - access_control = dictio.dict_read("resources", res_label_filename) - except: - pass - if oreslabel: - if not access_control.has_key(resource): - return -xsconstants.XSERR_BAD_LABEL - tmp = access_control[resource] - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL - if tmp[2] != oreslabel: - return -xsconstants.XSERR_BAD_LABEL - if reslabel != "": - new_entry = { resource : tuple([policytype, policyref, reslabel])} - access_control.update(new_entry) - else: - if access_control.has_key(resource): - del access_control[resource] - dictio.dict_write(access_control, "resources", res_label_filename) - finally: - __resfile_lock.release() - return xsconstants.XSERR_SUCCESS - -def rm_resource_label(resource, oldlabel_xapi): - """Remove a resource label from a physical resource - @param resource: The name of a resource, i.e., "phy:/dev/hda" - - @rtype: int - @return Success (0) or failure value (< 0) - """ - tmp = oldlabel_xapi.split(":") - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - otyp, opolicyref, olabel = tmp - # Only ACM is supported - if otyp != xsconstants.ACM_POLICY_ID and \ - otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID: - return -xsconstants.XSERR_WRONG_POLICY_TYPE - return set_resource_label(resource, "", "", "", olabel) - -def get_resource_label_xapi(resource): - """Get the assigned resource label of a physical resource - in the format used by then Xen-API, i.e., "ACM:xm-test:blue" - - @rtype: string - @return the string representing policy type, policy name and label of - the resource - """ - res = get_resource_label(resource) - return format_resource_label(res) - -def format_resource_label(res): - if res: - if len(res) == 2: - return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1] - if len(res) == 3: - return ":".join(res) - return "" - -def get_resource_label(resource): - """Get the assigned resource label of a given resource - @param resource: The name of a resource, i.e., "phy:/dev/hda" - - @rtype: list - @return tuple of (policy name, resource label), i.e., (xm-test, blue) - """ - try: - resource = unify_resname(resource, mustexist=False) - except Exception: - return [] - - reslabel_map = get_labeled_resources() - - if reslabel_map.has_key(resource): - return list(reslabel_map[resource]) - else: - #Try to resolve each label entry - for key, value in reslabel_map.items(): - try: - if resource == unify_resname(key): - return list(value) - except: - pass - - return [] - - -def get_labeled_resources_xapi(): - """ Get a map of all labeled resource with the labels formatted in the - xen-api resource label format. - """ - reslabel_map = get_labeled_resources() - for key, labeldata in reslabel_map.items(): - reslabel_map[key] = format_resource_label(labeldata) - return reslabel_map - - -def get_labeled_resources(): - """Get a map of all labeled resources - @rtype: list - @return list of labeled resources - """ - try: - __resfile_lock.acquire() - try: - access_control = dictio.dict_read("resources", res_label_filename) - except: - return {} - finally: - __resfile_lock.release() - return access_control - - -def relabel_domains(relabel_list): - """ - Relabel the given domains to have a new ssidref. - @param relabel_list: a list containing tuples of domid, ssidref - example: [ [0, 0x00020002] ] - """ - rel_rules = "" - for r in relabel_list: - log.info("Relabeling domain with domid %d to new ssidref 0x%08x", - r[0], r[1]) - rel_rules += struct.pack("ii", r[0], r[1]) - try: - rc, errors = acm.relabel_domains(rel_rules) - except Exception, e: - log.info("Error after relabel_domains: %s" % str(e)) - rc = -xsconstants.XSERR_GENERAL_FAILURE - errors = "" - if (len(errors) > 0): - rc = -xsconstants.XSERR_HV_OP_FAILED - return rc, errors - - -def change_acm_policy(bin_pol, del_array, chg_array, - vmlabel_map, reslabel_map, cur_acmpol, new_acmpol): - """ - Change the ACM policy of the system by relabeling - domains and resources first and doing some access checks. - Then update the policy in the hypervisor. If this is all successful, - relabel the domains permanently and commit the relabed resources. - - Need to do / check the following: - - relabel all resources where there is a 'from' field in - the policy. [ NOT DOING THIS: and mark those as unlabeled where the label - does not appear in the new policy anymore (deletion) ] - - relabel all VMs where there is a 'from' field in the - policy and mark those as unlabeled where the label - does not appear in the new policy anymore; no running - or paused VM may be unlabeled through this - - check that under the new labeling conditions the VMs - still have access to their resources as before. Unlabeled - resources are inaccessible. If this check fails, the - update failed. - - Attempt changes in the hypervisor; if this step fails, - roll back the relabeling of resources and VMs - - Make the relabeling of resources and VMs permanent - """ - rc = xsconstants.XSERR_SUCCESS - - domain_label_map = {} - new_policyname = new_acmpol.get_name() - new_policytype = new_acmpol.get_type_name() - cur_policyname = cur_acmpol.get_name() - cur_policytype = cur_acmpol.get_type_name() - polnew_reslabels = new_acmpol.policy_get_resourcelabel_names() - errors="" - - try: - __resfile_lock.acquire() - mapfile_lock() - - # Get all domains' dominfo. - from xen.xend import XendDomain - dominfos = XendDomain.instance().list('all') - - log.info("----------------------------------------------") - # relabel resources - - access_control = {} - try: - access_control = dictio.dict_read("resources", res_label_filename) - finally: - pass - for key, labeldata in access_control.items(): - if len(labeldata) == 2: - policy, label = labeldata - policytype = xsconstants.ACM_POLICY_ID - elif len(labeldata) == 3: - policytype, policy, label = labeldata - else: - return -xsconstants.XSERR_BAD_LABEL_FORMAT, "" - - if policytype != cur_policytype or \ - policy != cur_policyname: - continue - - # label been renamed or deleted? - if reslabel_map.has_key(label) and cur_policyname == policy: - label = reslabel_map[label] - elif label not in polnew_reslabels: - policytype = xsconstants.INVALID_POLICY_PREFIX + policytype - # Update entry - access_control[key] = \ - tuple([ policytype, new_policyname, label ]) - - # All resources have new labels in the access_control map - # There may still be labels in there that are invalid now. - - # Do this in memory without writing to disk: - # - Relabel all domains independent of whether they are running - # or not - # - later write back to config files - polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names() - - for dominfo in dominfos: - sec_lab = dominfo.get_security_label() - if not sec_lab: - continue - policytype, policy, vmlabel = sec_lab.split(":") - name = dominfo.getName() - - if policytype != cur_policytype or \ - policy != cur_policyname: - continue - - new_vmlabel = vmlabel - if vmlabel_map.has_key(vmlabel): - new_vmlabel = vmlabel_map[vmlabel] - if new_vmlabel not in polnew_vmlabels: - policytype = xsconstants.INVALID_POLICY_PREFIX + policytype - new_seclab = "%s:%s:%s" % \ - (policytype, new_policyname, new_vmlabel) - - domain_label_map[dominfo] = [ sec_lab, new_seclab ] - - if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING): - compatible = __resources_compatible_with_vmlabel(new_acmpol, - dominfo, - new_vmlabel, - access_control, - is_policy_update=True) - log.info("Domain %s with new label '%s' can access its " - "resources? : %s" % - (name, new_vmlabel, str(compatible))) - log.info("VM labels in new policy: %s" % - new_acmpol.policy_get_virtualmachinelabel_names()) - if not compatible: - return (-xsconstants.XSERR_RESOURCE_ACCESS, "") - - rc, errors = hv_chg_policy(bin_pol, del_array, chg_array) - if rc == 0: - # Write the relabeled resources back into the file - dictio.dict_write(access_control, "resources", res_label_filename) - # Properly update all VMs to their new labels - for dominfo, labels in domain_label_map.items(): - sec_lab, new_seclab = labels - if sec_lab != new_seclab: - log.info("Updating domain %s to new label '%s'." % \ - (dominfo.getName(), new_seclab)) - # This better be working! - res = dominfo.set_security_label(new_seclab, - sec_lab, - new_acmpol, - cur_acmpol) - if res[0] != xsconstants.XSERR_SUCCESS: - log.info("ERROR: Could not chg label on domain %s: %s" % - (dominfo.getName(), - xsconstants.xserr2string(-int(res[0])))) - finally: - log.info("----------------------------------------------") - mapfile_unlock() - __resfile_lock.release() - - return rc, errors diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/__init__.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,2 @@ + + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/acm/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/acm/__init__.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,1 @@ + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/acm/acm.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/acm/acm.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,1319 @@ +#=========================================================================== +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2006 International Business Machines Corp. +# Author: Reiner Sailer +# Author: Bryan D. Payne <bdpayne@xxxxxxxxxx> +# Author: Stefan Berger <stefanb@xxxxxxxxxx> +#============================================================================ + +import commands +import logging +import os, string, re +import threading +import struct +import stat +from xen.lowlevel import acm +from xen.xend import sxp +from xen.xend import XendConstants +from xen.xend.XendLogging import log +from xen.xend.XendError import VmError +from xen.util import dictio, xsconstants +from xen.xend.XendConstants import * + +#global directories and tools for security management +policy_dir_prefix = "/etc/xen/acm-security/policies" +res_label_filename = policy_dir_prefix + "/resource_labels" +boot_filename = "/boot/grub/menu.lst" +altboot_filename = "/boot/grub/grub.conf" +xensec_xml2bin = "/usr/sbin/xensec_xml2bin" +xensec_tool = "/usr/sbin/xensec_tool" + +#global patterns for map file +#police_reference_tagname = "POLICYREFERENCENAME" +primary_entry_re = re.compile("\s*PRIMARY\s+.*", re.IGNORECASE) +secondary_entry_re = re.compile("\s*SECONDARY\s+.*", re.IGNORECASE) +label_template_re = re.compile(".*security_label_template.xml", re.IGNORECASE) +mapping_filename_re = re.compile(".*\.map", re.IGNORECASE) +policy_reference_entry_re = re.compile("\s*POLICYREFERENCENAME\s+.*", re.IGNORECASE) +vm_label_re = re.compile("\s*LABEL->SSID\s+VM\s+.*", re.IGNORECASE) +res_label_re = re.compile("\s*LABEL->SSID\s+RES\s+.*", re.IGNORECASE) +all_label_re = re.compile("\s*LABEL->SSID\s+.*", re.IGNORECASE) +access_control_re = re.compile("\s*access_control\s*=", re.IGNORECASE) + +#global patterns for boot configuration file +xen_title_re = re.compile("\s*title\s+XEN", re.IGNORECASE) +any_title_re = re.compile("\s*title\s", re.IGNORECASE) +xen_kernel_re = re.compile("\s*kernel.*xen.*\.gz", re.IGNORECASE) +kernel_ver_re = re.compile("\s*module.*vmlinuz", re.IGNORECASE) +any_module_re = re.compile("\s*module\s", re.IGNORECASE) +empty_line_re = re.compile("^\s*$") +binary_name_re = re.compile(".*[chwall|ste|chwall_ste].*\.bin", re.IGNORECASE) +policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE) + +#decision hooks known to the hypervisor +ACMHOOK_sharing = 1 +ACMHOOK_authorization = 2 + +#other global variables +NULL_SSIDREF = 0 + +#general Rlock for map files; only one lock for all mapfiles +__mapfile_lock = threading.RLock() +__resfile_lock = threading.RLock() + +log = logging.getLogger("xend.util.security") + +# Our own exception definition. It is masked (pass) if raised and +# whoever raises this exception must provide error information. +class ACMError(Exception): + def __init__(self,value): + self.value = value + def __str__(self): + return repr(self.value) + + + +def err(msg): + """Raise ACM exception. + """ + raise ACMError(msg) + + + +active_policy = None + + +def mapfile_lock(): + __mapfile_lock.acquire() + +def mapfile_unlock(): + __mapfile_lock.release() + + +def refresh_security_policy(): + """ + retrieves security policy + """ + global active_policy + + try: + active_policy = acm.policy() + except: + active_policy = "INACTIVE" + +# now set active_policy +refresh_security_policy() + +def on(): + """ + returns none if security policy is off (not compiled), + any string otherwise, use it: if not security.on() ... + """ + refresh_security_policy() + return (active_policy not in ['INACTIVE', 'NULL']) + + +def calc_dom_ssidref_from_info(info): + """ + Calculate a domain's ssidref from the security_label in its + info. + This function is called before the domain is started and + makes sure that: + - the type of the policy is the same as indicated in the label + - the name of the policy is the same as indicated in the label + - calculates an up-to-date ssidref for the domain + The latter is necessary since the domain's ssidref could have + changed due to changes to the policy. + """ + import xen.xend.XendConfig + if isinstance(info, xen.xend.XendConfig.XendConfig): + if info.has_key('security_label'): + seclab = info['security_label'] + tmp = seclab.split(":") + if len(tmp) != 3: + raise VmError("VM label '%s' in wrong format." % seclab) + typ, policyname, vmlabel = seclab.split(":") + if typ != xsconstants.ACM_POLICY_ID: + raise VmError("Policy type '%s' must be changed." % typ) + refresh_security_policy() + if active_policy != policyname: + raise VmError("Active policy '%s' different than " + "what in VM's label ('%s')." % + (active_policy, policyname)) + ssidref = label2ssidref(vmlabel, policyname, "dom") + return ssidref + else: + return 0x0 + raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'" + "not supported." % type(info)) + + +def getmapfile(policyname): + """ + in: if policyname is None then the currently + active hypervisor policy is used + out: 1. primary policy, 2. secondary policy, + 3. open file descriptor for mapping file, and + 4. True if policy file is available, False otherwise + """ + if not policyname: + policyname = active_policy + map_file_ok = False + primary = None + secondary = None + #strip last part of policy as file name part + policy_dir_list = string.split(policyname, ".") + policy_file = policy_dir_list.pop() + if len(policy_dir_list) > 0: + policy_dir = string.join(policy_dir_list, "/") + "/" + else: + policy_dir = "" + + map_filename = policy_dir_prefix + "/" + policy_dir + policy_file + ".map" + # check if it is there, if not check if policy file is there + if not os.path.isfile(map_filename): + policy_filename = policy_dir_prefix + "/" + policy_dir + policy_file + "-security_policy.xml" + if not os.path.isfile(policy_filename): + err("Policy file \'" + policy_filename + "\' not found.") + else: + err("Mapping file \'" + map_filename + "\' not found." + + " Use xm makepolicy to create it.") + + f = open(map_filename) + for line in f: + if policy_reference_entry_re.match(line): + l = line.split() + if (len(l) == 2) and (l[1] == policyname): + map_file_ok = True + elif primary_entry_re.match(line): + l = line.split() + if len(l) == 2: + primary = l[1] + elif secondary_entry_re.match(line): + l = line.split() + if len(l) == 2: + secondary = l[1] + f.close() + f = open(map_filename) + if map_file_ok and primary and secondary: + return (primary, secondary, f, True) + else: + err("Mapping file inconsistencies found. Try makepolicy to create a new one.") + + + +def ssidref2label(ssidref_var): + """ + returns labelname corresponding to ssidref; + maps current policy to default directory + to find mapping file + """ + #1. translated permitted input formats + if isinstance(ssidref_var, str): + ssidref_var.strip() + if ssidref_var[0:2] == "0x": + ssidref = int(ssidref_var[2:], 16) + else: + ssidref = int(ssidref_var) + elif isinstance(ssidref_var, int): + ssidref = ssidref_var + else: + err("Instance type of ssidref not supported (must be of type 'str' or 'int')") + + if ssidref == 0: + from xen.util.acmpolicy import ACM_LABEL_UNLABELED + return ACM_LABEL_UNLABELED + + try: + mapfile_lock() + + (primary, secondary, f, pol_exists) = getmapfile(None) + if not f: + if (pol_exists): + err("Mapping file for policy not found.\n" + + "Please use makepolicy command to create mapping file!") + else: + err("Policy file for \'" + active_policy + "\' not found.") + + #2. get labelnames for both ssidref parts + pri_ssid = ssidref & 0xffff + sec_ssid = ssidref >> 16 + pri_null_ssid = NULL_SSIDREF & 0xffff + sec_null_ssid = NULL_SSIDREF >> 16 + pri_labels = [] + sec_labels = [] + labels = [] + + for line in f: + l = line.split() + if (len(l) < 5) or (l[0] != "LABEL->SSID"): + continue + if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid): + pri_labels.append(l[3]) + if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid): + sec_labels.append(l[3]) + f.close() + finally: + mapfile_unlock() + + #3. get the label that is in both lists (combination must be a single label) + if (primary == "CHWALL") and (pri_ssid == pri_null_ssid) and (sec_ssid != sec_null_ssid): + labels = sec_labels + elif (secondary == "CHWALL") and (pri_ssid != pri_null_ssid) and (sec_ssid == sec_null_ssid): + labels = pri_labels + elif secondary == "NULL": + labels = pri_labels + else: + for i in pri_labels: + for j in sec_labels: + if (i==j): + labels.append(i) + if len(labels) != 1: + err("Label for ssidref \'" + str(ssidref) + + "\' unknown or not unique in policy \'" + active_policy + "\'") + + return labels[0] + + + +def label2ssidref(labelname, policyname, typ): + """ + returns ssidref corresponding to labelname; + maps current policy to default directory + to find mapping file """ + + if policyname in ['NULL', 'INACTIVE', 'DEFAULT']: + err("Cannot translate labels for \'" + policyname + "\' policy.") + + allowed_types = ['ANY'] + if typ == 'dom': + allowed_types.append('VM') + elif typ == 'res': + allowed_types.append('RES') + else: + err("Invalid type. Must specify 'dom' or 'res'.") + + try: + mapfile_lock() + (primary, secondary, f, pol_exists) = getmapfile(policyname) + + #2. get labelnames for ssidref parts and find a common label + pri_ssid = [] + sec_ssid = [] + for line in f: + l = line.split() + if (len(l) < 5) or (l[0] != "LABEL->SSID"): + continue + if primary and (l[1] in allowed_types) and \ + (l[2] == primary) and \ + (l[3] == labelname): + pri_ssid.append(int(l[4], 16)) + if secondary and (l[1] in allowed_types) and \ + (l[2] == secondary) and \ + (l[3] == labelname): + sec_ssid.append(int(l[4], 16)) + f.close() + if (typ == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0): + pri_ssid.append(NULL_SSIDREF) + elif (typ == 'res') and (secondary == "CHWALL") and \ + (len(sec_ssid) == 0): + sec_ssid.append(NULL_SSIDREF) + + #3. sanity check and composition of ssidref + if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and \ + (secondary != "NULL")): + err("Label \'" + labelname + "\' not found.") + elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1): + err("Label \'" + labelname + "\' not unique in policy (policy error)") + if secondary == "NULL": + return pri_ssid[0] + else: + return (sec_ssid[0] << 16) | pri_ssid[0] + finally: + mapfile_unlock() + + +def refresh_ssidref(config): + """ + looks up ssidref from security field + and refreshes the value if label exists + """ + #called by dom0, policy could have changed after xen.utils.security was initialized + refresh_security_policy() + + security = None + if isinstance(config, dict): + security = config['security'] + elif isinstance(config, list): + security = sxp.child_value(config, 'security') + else: + err("Instance type of config parameter not supported.") + if not security: + #nothing to do (no security label attached) + return config + + policyname = None + labelname = None + # compose new security field + for idx in range(0, len(security)): + if security[idx][0] == 'ssidref': + security.pop(idx) + break + elif security[idx][0] == 'access_control': + for jdx in [1, 2]: + if security[idx][jdx][0] == 'label': + labelname = security[idx][jdx][1] + elif security[idx][jdx][0] == 'policy': + policyname = security[idx][jdx][1] + else: + err("Illegal field in access_control") + #verify policy is correct + if active_policy != policyname: + err("Policy \'" + str(policyname) + + "\' in label does not match active policy \'" + + str(active_policy) +"\'!") + + new_ssidref = label2ssidref(labelname, policyname, 'dom') + if not new_ssidref: + err("SSIDREF refresh failed!") + + security.append([ 'ssidref',str(new_ssidref)]) + security = ['security', security ] + + for idx in range(0,len(config)): + if config[idx][0] == 'security': + config.pop(idx) + break + config.append(security) + + + +def get_ssid(domain): + """ + enables domains to retrieve the label / ssidref of a running domain + """ + if not on(): + err("No policy active.") + + if isinstance(domain, str): + domain_int = int(domain) + elif isinstance(domain, int): + domain_int = domain + else: + err("Illegal parameter type.") + try: + ssid_info = acm.getssid(int(domain_int)) + except: + err("Cannot determine security information.") + + if active_policy in ["DEFAULT"]: + label = "DEFAULT" + else: + label = ssidref2label(ssid_info["ssidref"]) + return(ssid_info["policyreference"], + label, + ssid_info["policytype"], + ssid_info["ssidref"]) + + + +def get_decision(arg1, arg2): + """ + enables domains to retrieve access control decisions from + the hypervisor Access Control Module. + IN: args format = ['domid', id] or ['ssidref', ssidref] + or ['access_control', ['policy', policy], ['label', label], ['type', type]] + """ + + if not on(): + err("No policy active.") + + #translate labels before calling low-level function + if arg1[0] == 'access_control': + if (arg1[1][0] != 'policy') or (arg1[2][0] != 'label') or (arg1[3][0] != 'type'): + err("Argument type not supported.") + ssidref = label2ssidref(arg1[2][1], arg1[1][1], arg1[3][1]) + arg1 = ['ssidref', str(ssidref)] + if arg2[0] == 'access_control': + if (arg2[1][0] != 'policy') or (arg2[2][0] != 'label') or (arg2[3][0] != 'type'): + err("Argument type not supported.") + ssidref = label2ssidref(arg2[2][1], arg2[1][1], arg2[3][1]) + arg2 = ['ssidref', str(ssidref)] + + # accept only int or string types for domid and ssidref + if isinstance(arg1[1], int): + arg1[1] = str(arg1[1]) + if isinstance(arg2[1], int): + arg2[1] = str(arg2[1]) + if not isinstance(arg1[1], str) or not isinstance(arg2[1], str): + err("Invalid id or ssidref type, string or int required") + + try: + decision = acm.getdecision(arg1[0], arg1[1], arg2[0], arg2[1], + ACMHOOK_sharing) + except: + err("Cannot determine decision.") + + if decision: + return decision + else: + err("Cannot determine decision (Invalid parameter).") + + +def has_authorization(ssidref): + """ Check if the domain with the given ssidref has authorization to + run on this system. To have authoriztion dom0's STE types must + be a superset of that of the domain's given through its ssidref. + """ + rc = True + dom0_ssidref = int(acm.getssid(0)['ssidref']) + decision = acm.getdecision('ssidref', str(dom0_ssidref), + 'ssidref', str(ssidref), + ACMHOOK_authorization) + if decision == "DENIED": + rc = False + return rc + + +def hv_chg_policy(bin_pol, del_array, chg_array): + """ + Change the binary policy in the hypervisor + The 'del_array' and 'chg_array' give hints about deleted ssidrefs + and changed ssidrefs which can be due to deleted VM labels + or reordered VM labels + """ + rc = -xsconstants.XSERR_GENERAL_FAILURE + errors = "" + if not on(): + err("No policy active.") + try: + rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array) + except Exception, e: + pass + if len(errors) > 0: + rc = -xsconstants.XSERR_HV_OP_FAILED + return rc, errors + + +def make_policy(policy_name): + policy_file = string.join(string.split(policy_name, "."), "/") + if not os.path.isfile(policy_dir_prefix + "/" + policy_file + "-security_policy.xml"): + err("Unknown policy \'" + policy_name + "\'") + + (ret, output) = commands.getstatusoutput(xensec_xml2bin + " -d " + policy_dir_prefix + " " + policy_file) + if ret: + err("Creating policy failed:\n" + output) + +def load_policy(policy_name): + global active_policy + policy_file = policy_dir_prefix + "/" + string.join(string.split(policy_name, "."), "/") + if not os.path.isfile(policy_file + ".bin"): + if os.path.isfile(policy_file + "-security_policy.xml"): + err("Binary file does not exist." + + "Please use makepolicy to build the policy binary.") + else: + err("Unknown Policy " + policy_name) + + #require this policy to be the first or the same as installed + if active_policy not in ['DEFAULT', policy_name]: + err("Active policy \'" + active_policy + + "\' incompatible with new policy \'" + policy_name + "\'") + (ret, output) = commands.getstatusoutput(xensec_tool + " loadpolicy " + policy_file + ".bin") + if ret: + err("Loading policy failed:\n" + output) + else: + # refresh active policy + refresh_security_policy() + + + +def dump_policy(): + if active_policy in ['NULL', 'INACTIVE']: + err("\'" + active_policy + "\' policy. Nothing to dump.") + + (ret, output) = commands.getstatusoutput(xensec_tool + " getpolicy") + if ret: + err("Dumping hypervisor policy failed:\n" + output) + print output + + + +def list_labels(policy_name, condition): + if (not policy_name) and (active_policy) in ["NULL", "INACTIVE", "DEFAULT"]: + err("Current policy \'" + active_policy + "\' has no labels defined.\n") + + (primary, secondary, f, pol_exists) = getmapfile(policy_name) + if not f: + if pol_exists: + err("Cannot find mapfile for policy \'" + policy_name + + "\'.\nPlease use makepolicy to create mapping file.") + else: + err("Unknown policy \'" + policy_name + "\'") + + labels = [] + for line in f: + if condition.match(line): + label = line.split()[3] + if label not in labels: + labels.append(label) + return labels + + +def get_res_label(resource): + """Returns resource label information (policytype, label, policy) if + it exists. Otherwise returns null label and policy. + """ + def default_res_label(): + ssidref = NULL_SSIDREF + if on(): + label = ssidref2label(ssidref) + else: + label = None + return (xsconstants.ACM_POLICY_ID, 'NULL', label) + + + tmp = get_resource_label(resource) + if len(tmp) == 2: + policytype = xsconstants.ACM_POLICY_ID + policy, label = tmp + elif len(tmp) == 3: + policytype, policy, label = tmp + else: + policytype, policy, label = default_res_label() + + return (policytype, label, policy) + + +def get_res_security_details(resource): + """Returns the (label, ssidref, policy) associated with a given + resource from the global resource label file. + """ + def default_security_details(): + ssidref = NULL_SSIDREF + if on(): + label = ssidref2label(ssidref) + else: + label = None + policy = active_policy + return (label, ssidref, policy) + + (label, ssidref, policy) = default_security_details() + + # find the entry associated with this resource + (policytype, label, policy) = get_res_label(resource) + if policy == 'NULL': + log.info("Resource label for "+resource+" not in file, using DEFAULT.") + return default_security_details() + + # is this resource label for the running policy? + if policy == active_policy: + ssidref = label2ssidref(label, policy, 'res') + else: + log.info("Resource label not for active policy, using DEFAULT.") + return default_security_details() + + return (label, ssidref, policy) + +def security_label_to_details(seclab): + """ Convert a Xen-API type of security label into details """ + def default_security_details(): + ssidref = NULL_SSIDREF + if on(): + label = ssidref2label(ssidref) + else: + label = None + policy = active_policy + return (label, ssidref, policy) + + (policytype, policy, label) = seclab.split(":") + + # is this resource label for the running policy? + if policy == active_policy: + ssidref = label2ssidref(label, policy, 'res') + else: + log.info("Resource label not for active policy, using DEFAULT.") + return default_security_details() + + return (label, ssidref, policy) + +def unify_resname(resource, mustexist=True): + """Makes all resource locations absolute. In case of physical + resources, '/dev/' is added to local file names""" + + if not resource: + return resource + + # sanity check on resource name + try: + (typ, resfile) = resource.split(":", 1) + except: + err("Resource spec '%s' contains no ':' delimiter" % resource) + + if typ == "tap": + try: + (subtype, resfile) = resfile.split(":") + except: + err("Resource spec '%s' contains no tap subtype" % resource) + + import os + if typ in ["phy", "tap"]: + if not resfile.startswith("/"): + resfile = "/dev/" + resfile + if mustexist: + stats = os.lstat(resfile) + if stat.S_ISLNK(stats[stat.ST_MODE]): + resolved = os.readlink(resfile) + if resolved[0] != "/": + resfile = os.path.join(os.path.dirname(resfile), resolved) + resfile = os.path.abspath(resfile) + else: + resfile = resolved + stats = os.lstat(resfile) + if not (stat.S_ISBLK(stats[stat.ST_MODE])): + err("Invalid resource") + + if typ in [ "file", "tap" ]: + if mustexist: + stats = os.lstat(resfile) + if stat.S_ISLNK(stats[stat.ST_MODE]): + resfile = os.readlink(resfile) + stats = os.lstat(resfile) + if not stat.S_ISREG(stats[stat.ST_MODE]): + err("Invalid resource") + + #file: resources must specified with absolute path + #vlan resources don't start with '/' + if typ != "vlan": + if (not resfile.startswith("/")) or \ + (mustexist and not os.path.exists(resfile)): + err("Invalid resource.") + + # from here on absolute file names with resources + if typ == "tap": + typ = typ + ":" + subtype + resource = typ + ":" + resfile + return resource + + +def res_security_check(resource, domain_label): + """Checks if the given resource can be used by the given domain + label. Returns 1 if the resource can be used, otherwise 0. + """ + rtnval = 1 + + # if security is on, ask the hypervisor for a decision + if on(): + #build canonical resource name + resource = unify_resname(resource) + + (label, ssidref, policy) = get_res_security_details(resource) + domac = ['access_control'] + domac.append(['policy', active_policy]) + domac.append(['label', domain_label]) + domac.append(['type', 'dom']) + decision = get_decision(domac, ['ssidref', str(ssidref)]) + + # provide descriptive error messages + if decision == 'DENIED': + if label == ssidref2label(NULL_SSIDREF): + raise ACMError("Resource '"+resource+"' is not labeled") + rtnval = 0 + else: + raise ACMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed") + rtnval = 0 + + # security is off, make sure resource isn't labeled + else: + # Note, we can't canonicalise the resource here, because people using + # xm without ACM are free to use relative paths. + (policytype, label, policy) = get_res_label(resource) + if policy != 'NULL': + raise ACMError("Security is off, but '"+resource+"' is labeled") + rtnval = 0 + + return rtnval + +def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label): + """Checks if the given resource can be used by the given domain + label. Returns 1 if the resource can be used, otherwise 0. + """ + rtnval = 1 + # if security is on, ask the hypervisor for a decision + if on(): + typ, dpolicy, domain_label = xapi_dom_label.split(":") + if not dpolicy or not domain_label: + raise VmError("VM security label in wrong format.") + if active_policy != rpolicy: + raise VmError("Resource's policy '%s' != active policy '%s'" % + (rpolicy, active_policy)) + domac = ['access_control'] + domac.append(['policy', active_policy]) + domac.append(['label', domain_label]) + domac.append(['type', 'dom']) + decision = get_decision(domac, ['ssidref', str(rssidref)]) + + log.info("Access Control Decision : %s" % decision) + # provide descriptive error messages + if decision == 'DENIED': + if rlabel == ssidref2label(NULL_SSIDREF): + #raise ACMError("Resource is not labeled") + rtnval = 0 + else: + #raise ACMError("Permission denied for resource because label '"+rlabel+"' is not allowed") + rtnval = 0 + + # security is off, make sure resource isn't labeled + else: + # Note, we can't canonicalise the resource here, because people using + # xm without ACM are free to use relative paths. + if rpolicy != 'NULL': + #raise ACMError("Security is off, but resource is labeled") + rtnval = 0 + + return rtnval + + +def validate_label(label, policyref): + """ + Make sure that this label is part of the currently enforced policy + and that it reference the current policy. + """ + rc = xsconstants.XSERR_SUCCESS + from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance + curpol = XSPolicyAdminInstance().get_loaded_policy() + if not curpol or curpol.get_name() != policyref: + rc = -xsconstants.XSERR_BAD_LABEL + else: + try: + label2ssidref(label, curpol.get_name() , 'res') + except: + rc = -xsconstants.XSERR_BAD_LABEL + return rc + + +def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi): + """Assign a resource label to a resource + @param resource: The name of a resource, i.e., "phy:/dev/hda", or + "tap:qcow:/path/to/file.qcow" + + @param reslabel_xapi: A resource label foramtted as in all other parts of + the Xen-API, i.e., ACM:xm-test:blue" + @rtype: int + @return Success (0) or failure value (< 0) + """ + olabel = "" + if reslabel_xapi == "": + return rm_resource_label(resource, oldlabel_xapi) + typ, policyref, label = reslabel_xapi.split(":") + if typ != xsconstants.ACM_POLICY_ID: + return -xsconstants.XSERR_WRONG_POLICY_TYPE + if not policyref or not label: + return -xsconstants.XSERR_BAD_LABEL_FORMAT + if oldlabel_xapi not in [ "" ]: + tmp = oldlabel_xapi.split(":") + if len(tmp) != 3: + return -xsconstants.XSERR_BAD_LABEL_FORMAT + otyp, opolicyref, olabel = tmp + # Only ACM is supported + if otyp != xsconstants.ACM_POLICY_ID and \ + otyp != xsconstants.INVALID_POLICY_PREFIX + \ + xsconstants.ACM_POLICY_ID: + return -xsconstants.XSERR_WRONG_POLICY_TYPE + rc = validate_label(label, policyref) + if rc != xsconstants.XSERR_SUCCESS: + return rc + return set_resource_label(resource, typ, policyref, label, olabel) + + +def is_resource_in_use(resource): + """ + Domain-0 'owns' resources of type 'VLAN', the rest are owned by + the guests. + """ + from xen.xend import XendDomain + lst = [] + if resource.startswith('vlan'): + from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance + curpol = XSPolicyAdminInstance().get_loaded_policy() + policytype, label, policy = get_res_label(resource) + if curpol and \ + policytype == xsconstants.ACM_POLICY_ID and \ + policy == curpol.get_name() and \ + label in curpol.policy_get_resourcelabel_names(): + # VLAN is in use. + lst.append(XendDomain.instance(). + get_vm_by_uuid(XendDomain.DOM0_UUID)) + else: + dominfos = XendDomain.instance().list('all') + for dominfo in dominfos: + if is_resource_in_use_by_dom(dominfo, resource): + lst.append(dominfo) + return lst + +def devices_equal(res1, res2, mustexist=True): + """ Determine whether two devices are equal """ + return (unify_resname(res1, mustexist) == + unify_resname(res2, mustexist)) + +def is_resource_in_use_by_dom(dominfo, resource): + """ Determine whether a resources is in use by a given domain + @return True or False + """ + if not dominfo.domid: + return False + if dominfo._stateGet() not in [ DOM_STATE_RUNNING ]: + return False + devs = dominfo.info['devices'] + uuids = devs.keys() + for uuid in uuids: + dev = devs[uuid] + if len(dev) >= 2 and dev[1].has_key('uname'): + # dev[0] is type, i.e. 'vbd' + if devices_equal(dev[1]['uname'], resource, mustexist=False): + log.info("RESOURCE IN USE: Domain %d uses %s." % + (dominfo.domid, resource)) + return True + return False + + +def get_domain_resources(dominfo): + """ Collect all resources of a domain in a map where each entry of + the map is a list. + Entries are strored in the following formats: + tap:qcow:/path/xyz.qcow + """ + resources = { 'vbd' : [], 'tap' : [], 'vif' : []} + devs = dominfo.info['devices'] + uuids = devs.keys() + for uuid in uuids: + dev = devs[uuid] + typ = dev[0] + if typ in [ 'vbd', 'tap' ]: + resources[typ].append(dev[1]['uname']) + if typ in [ 'vif' ]: + sec_lab = dev[1].get('security_label') + if sec_lab: + resources[typ].append(sec_lab) + else: + # !!! This should really get the label of the domain + # or at least a resource label that has the same STE type + # as the domain has + from xen.util.acmpolicy import ACM_LABEL_UNLABELED + resources[typ].append("%s:%s:%s" % + (xsconstants.ACM_POLICY_ID, + active_policy, + ACM_LABEL_UNLABELED)) + + return resources + + +def resources_compatible_with_vmlabel(xspol, dominfo, vmlabel): + """ + Check whether the resources' labels are compatible with the + given VM label. This is a function to be used when for example + a running domain is to get the new label 'vmlabel' + """ + if not xspol: + return False + + try: + __resfile_lock.acquire() + try: + access_control = dictio.dict_read("resources", + res_label_filename) + except: + # No labeled resources -> must be compatible + return True + return __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel, + access_control) + finally: + __resfile_lock.release() + return False + + +def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel, + access_control, + is_policy_update=False): + """ + Check whether the resources' labels are compatible with the + given VM label. The access_control parameter provides a + dictionary of the resource name to resource label mappings + under which the evaluation should be done. + Call this only for a paused or running domain. + """ + def collect_labels(reslabels, s_label, polname): + if len(s_label) != 3 or polname != s_label[1]: + return False + label = s_label[2] + if not label in reslabels: + reslabels.append(label) + return True + + resources = get_domain_resources(dominfo) + reslabels = [] # all resource labels + + polname = xspol.get_name() + for key, value in resources.items(): + if key in [ 'vbd', 'tap' ]: + for res in resources[key]: + try: + label = access_control[res] + if not collect_labels(reslabels, label, polname): + return False + except: + return False + elif key in [ 'vif' ]: + for xapi_label in value: + label = xapi_label.split(":") + from xen.util.acmpolicy import ACM_LABEL_UNLABELED + if not (is_policy_update and \ + label[2] == ACM_LABEL_UNLABELED): + if not collect_labels(reslabels, label, polname): + return False + else: + log.error("Unhandled device type: %s" % key) + return False + + # Check that all resource labes have a common STE type with the + # vmlabel + if len(reslabels) > 0: + rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels) + else: + rc = True + log.info("vmlabel=%s, reslabels=%s, rc=%s" % + (vmlabel, reslabels, str(rc))) + return rc; + +def set_resource_label(resource, policytype, policyref, reslabel, \ + oreslabel = None): + """Assign a label to a resource + If the old label (oreslabel) is given, then the resource must have + that old label. + A resource label may be changed if + - the resource is not in use + @param resource : The name of a resource, i.e., "phy:/dev/hda" + @param policyref : The name of the policy + @param reslabel : the resource label within the policy + @param oreslabel : optional current resource label + + @rtype: int + @return Success (0) or failure value (< 0) + """ + try: + resource = unify_resname(resource, mustexist=False) + except Exception: + return -xsconstants.XSERR_BAD_RESOURCE_FORMAT + + domains = is_resource_in_use(resource) + if len(domains) > 0: + return -xsconstants.XSERR_RESOURCE_IN_USE + + try: + __resfile_lock.acquire() + access_control = {} + try: + access_control = dictio.dict_read("resources", res_label_filename) + except: + pass + if oreslabel: + if not access_control.has_key(resource): + return -xsconstants.XSERR_BAD_LABEL + tmp = access_control[resource] + if len(tmp) != 3: + return -xsconstants.XSERR_BAD_LABEL + if tmp[2] != oreslabel: + return -xsconstants.XSERR_BAD_LABEL + if reslabel != "": + new_entry = { resource : tuple([policytype, policyref, reslabel])} + access_control.update(new_entry) + else: + if access_control.has_key(resource): + del access_control[resource] + dictio.dict_write(access_control, "resources", res_label_filename) + finally: + __resfile_lock.release() + return xsconstants.XSERR_SUCCESS + +def rm_resource_label(resource, oldlabel_xapi): + """Remove a resource label from a physical resource + @param resource: The name of a resource, i.e., "phy:/dev/hda" + + @rtype: int + @return Success (0) or failure value (< 0) + """ + tmp = oldlabel_xapi.split(":") + if len(tmp) != 3: + return -xsconstants.XSERR_BAD_LABEL_FORMAT + otyp, opolicyref, olabel = tmp + # Only ACM is supported + if otyp != xsconstants.ACM_POLICY_ID and \ + otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID: + return -xsconstants.XSERR_WRONG_POLICY_TYPE + return set_resource_label(resource, "", "", "", olabel) + +def get_resource_label_xapi(resource): + """Get the assigned resource label of a physical resource + in the format used by then Xen-API, i.e., "ACM:xm-test:blue" + + @rtype: string + @return the string representing policy type, policy name and label of + the resource + """ + res = get_resource_label(resource) + return format_resource_label(res) + +def format_resource_label(res): + if res: + if len(res) == 2: + return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1] + if len(res) == 3: + return ":".join(res) + return "" + +def get_resource_label(resource): + """Get the assigned resource label of a given resource + @param resource: The name of a resource, i.e., "phy:/dev/hda" + + @rtype: list + @return tuple of (policy name, resource label), i.e., (xm-test, blue) + """ + try: + resource = unify_resname(resource, mustexist=False) + except Exception: + return [] + + reslabel_map = get_labeled_resources() + + if reslabel_map.has_key(resource): + return list(reslabel_map[resource]) + else: + #Try to resolve each label entry + for key, value in reslabel_map.items(): + try: + if resource == unify_resname(key): + return list(value) + except: + pass + + return [] + + +def get_labeled_resources_xapi(): + """ Get a map of all labeled resource with the labels formatted in the + xen-api resource label format. + """ + reslabel_map = get_labeled_resources() + for key, labeldata in reslabel_map.items(): + reslabel_map[key] = format_resource_label(labeldata) + return reslabel_map + + +def get_labeled_resources(): + """Get a map of all labeled resources + @rtype: list + @return list of labeled resources + """ + try: + __resfile_lock.acquire() + try: + access_control = dictio.dict_read("resources", res_label_filename) + except: + return {} + finally: + __resfile_lock.release() + return access_control + + +def relabel_domains(relabel_list): + """ + Relabel the given domains to have a new ssidref. + @param relabel_list: a list containing tuples of domid, ssidref + example: [ [0, 0x00020002] ] + """ + rel_rules = "" + for r in relabel_list: + log.info("Relabeling domain with domid %d to new ssidref 0x%08x", + r[0], r[1]) + rel_rules += struct.pack("ii", r[0], r[1]) + try: + rc, errors = acm.relabel_domains(rel_rules) + except Exception, e: + log.info("Error after relabel_domains: %s" % str(e)) + rc = -xsconstants.XSERR_GENERAL_FAILURE + errors = "" + if (len(errors) > 0): + rc = -xsconstants.XSERR_HV_OP_FAILED + return rc, errors + + +def change_acm_policy(bin_pol, del_array, chg_array, + vmlabel_map, reslabel_map, cur_acmpol, new_acmpol): + """ + Change the ACM policy of the system by relabeling + domains and resources first and doing some access checks. + Then update the policy in the hypervisor. If this is all successful, + relabel the domains permanently and commit the relabed resources. + + Need to do / check the following: + - relabel all resources where there is a 'from' field in + the policy. [ NOT DOING THIS: and mark those as unlabeled where the label + does not appear in the new policy anymore (deletion) ] + - relabel all VMs where there is a 'from' field in the + policy and mark those as unlabeled where the label + does not appear in the new policy anymore; no running + or paused VM may be unlabeled through this + - check that under the new labeling conditions the VMs + still have access to their resources as before. Unlabeled + resources are inaccessible. If this check fails, the + update failed. + - Attempt changes in the hypervisor; if this step fails, + roll back the relabeling of resources and VMs + - Make the relabeling of resources and VMs permanent + """ + rc = xsconstants.XSERR_SUCCESS + + domain_label_map = {} + new_policyname = new_acmpol.get_name() + new_policytype = new_acmpol.get_type_name() + cur_policyname = cur_acmpol.get_name() + cur_policytype = cur_acmpol.get_type_name() + polnew_reslabels = new_acmpol.policy_get_resourcelabel_names() + errors="" + + try: + __resfile_lock.acquire() + mapfile_lock() + + # Get all domains' dominfo. + from xen.xend import XendDomain + dominfos = XendDomain.instance().list('all') + + log.info("----------------------------------------------") + # relabel resources + + access_control = {} + try: + access_control = dictio.dict_read("resources", res_label_filename) + except: + pass + for key, labeldata in access_control.items(): + if len(labeldata) == 2: + policy, label = labeldata + policytype = xsconstants.ACM_POLICY_ID + elif len(labeldata) == 3: + policytype, policy, label = labeldata + else: + return -xsconstants.XSERR_BAD_LABEL_FORMAT, "" + + if policytype != cur_policytype or \ + policy != cur_policyname: + continue + + # label been renamed or deleted? + if reslabel_map.has_key(label) and cur_policyname == policy: + label = reslabel_map[label] + elif label not in polnew_reslabels: + policytype = xsconstants.INVALID_POLICY_PREFIX + policytype + # Update entry + access_control[key] = \ + tuple([ policytype, new_policyname, label ]) + + # All resources have new labels in the access_control map + # There may still be labels in there that are invalid now. + + # Do this in memory without writing to disk: + # - Relabel all domains independent of whether they are running + # or not + # - later write back to config files + polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names() + + for dominfo in dominfos: + sec_lab = dominfo.get_security_label() + if not sec_lab: + continue + policytype, policy, vmlabel = sec_lab.split(":") + name = dominfo.getName() + + if policytype != cur_policytype or \ + policy != cur_policyname: + continue + + new_vmlabel = vmlabel + if vmlabel_map.has_key(vmlabel): + new_vmlabel = vmlabel_map[vmlabel] + if new_vmlabel not in polnew_vmlabels: + policytype = xsconstants.INVALID_POLICY_PREFIX + policytype + new_seclab = "%s:%s:%s" % \ + (policytype, new_policyname, new_vmlabel) + + domain_label_map[dominfo] = [ sec_lab, new_seclab ] + + if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING): + compatible = __resources_compatible_with_vmlabel(new_acmpol, + dominfo, + new_vmlabel, + access_control, + is_policy_update=True) + log.info("Domain %s with new label '%s' can access its " + "resources? : %s" % + (name, new_vmlabel, str(compatible))) + log.info("VM labels in new policy: %s" % + new_acmpol.policy_get_virtualmachinelabel_names()) + if not compatible: + return (-xsconstants.XSERR_RESOURCE_ACCESS, "") + + rc, errors = hv_chg_policy(bin_pol, del_array, chg_array) + if rc == 0: + # Write the relabeled resources back into the file + dictio.dict_write(access_control, "resources", res_label_filename) + # Properly update all VMs to their new labels + for dominfo, labels in domain_label_map.items(): + sec_lab, new_seclab = labels + if sec_lab != new_seclab: + log.info("Updating domain %s to new label '%s'." % \ + (dominfo.getName(), new_seclab)) + # This better be working! + res = dominfo.set_security_label(new_seclab, + sec_lab, + new_acmpol, + cur_acmpol) + if res[0] != xsconstants.XSERR_SUCCESS: + log.info("ERROR: Could not chg label on domain %s: %s" % + (dominfo.getName(), + xsconstants.xserr2string(-int(res[0])))) + finally: + log.info("----------------------------------------------") + mapfile_unlock() + __resfile_lock.release() + + return rc, errors + +def parse_security_label(security_label): + tmp = security_label.split(":") + if len(tmp) != 3: + return "" + else: + return security_label + +def set_security_label(policy, label): + policytype = xsconstants.ACM_POLICY_ID + if label != "" and policy != "": + return "%s:%s:%s" % (policytype, policy, label) + else: + return "" + +def ssidref2security_label(ssidref): + from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance + return XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/dummy/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/dummy/__init__.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,1 @@ + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/dummy/dummy.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/dummy/dummy.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,53 @@ +import sys + +class XSMError(Exception): + def __init__(self,value): + self.value = value + def __str__(self): + return repr(self.value) + +policy_dir_prefix = ""; +active_policy = ""; +NULL_SSIDREF = 0; + +def err(msg): + """Raise XSM-dummy exception. + """ + sys.stderr.write("XSM-dummyError: " + msg + "\n") + raise XSMError(msg) + +def on(): + return 0 + +def ssidref2label(ssidref): + return 0 + +def label2ssidref(label, policy, type): + return 0 + +def res_security_check(resource, domain_label): + return 1 + +def get_res_security_details(resource): + return ("","","") + +def get_res_label(resource): + return ("","") + +def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label): + return 1 + +def parse_security_label(security_label): + return "" + +def calc_dom_ssidref_from_info(info): + return "" + +def set_security_label(policy, label): + return "" + +def ssidref2security_label(ssidref): + return "" + +def has_authorization(ssidref): + return True diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/flask/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/flask/__init__.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,1 @@ + diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/flask/flask.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/flask/flask.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,37 @@ +import sys +from xen.lowlevel import flask +from xen.xend import sxp + +def err(msg): + """Raise XSM-Flask exception. + """ + sys.stderr.write("XSM-FlaskError: " + msg + "\n") + raise XSMError(msg) + +def on(): + return 1 + +def ssidref2label(ssidref): + try: + return flask.flask_sid_to_context(ssidref) + except: + return "" + +def label2ssidref(label, policy, type): + try: + return flask.flask_context_to_sid(label) + except: + return "" + +def parse_security_label(security_label): + return security_label + +def calc_dom_ssidref_from_info(info): + ssidref = label2ssidref(info['security_label'], "", "") + return ssidref + +def set_security_label(policy, label): + return label + +def ssidref2security_label(ssidref): + return ssidref2label(ssidref) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/util/xsm/xsm_core.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xsm/xsm_core.py Thu Sep 06 12:05:15 2007 -0600 @@ -0,0 +1,7 @@ +import sys +import xen.util.xsm.dummy.dummy as dummy + +def xsm_init(self): + for op in dir(dummy): + if not hasattr(self, op): + setattr(self, op, getattr(dummy, op, None)) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/XendCheckpoint.py Thu Sep 06 12:05:15 2007 -0600 @@ -16,7 +16,7 @@ import xen.util.auxbin import xen.util.auxbin import xen.lowlevel.xc -from xen.xend import balloon, sxp +from xen.xend import balloon, sxp, image from xen.xend.XendError import XendError, VmError from xen.xend.XendLogging import log from xen.xend.XendConfig import XendConfig @@ -181,8 +181,6 @@ def restore(xd, fd, dominfo = None, paus assert store_port assert console_port - nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 - # if hvm, pass mem size to calculate the store_mfn image_cfg = dominfo.info.get('image', {}) is_hvm = dominfo.info.is_hvm() @@ -196,18 +194,31 @@ def restore(xd, fd, dominfo = None, paus pae = 0 try: - shadow = dominfo.info['shadow_memory'] + restore_image = image.create(dominfo, dominfo.info) + memory = restore_image.getRequiredAvailableMemory( + dominfo.info['memory_dynamic_max'] / 1024) + maxmem = restore_image.getRequiredAvailableMemory( + dominfo.info['memory_static_max'] / 1024) + shadow = restore_image.getRequiredShadowMemory( + dominfo.info['shadow_memory'] / 1024, + dominfo.info['memory_static_max'] / 1024) + log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, ", dominfo.info['shadow_memory'], dominfo.info['memory_static_max'], dominfo.info['memory_static_min']) - balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024) - - shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow) + # Round shadow up to a multiple of a MiB, as shadow_mem_control + # takes MiB and we must not round down and end up under-providing. + shadow = ((shadow + 1023) / 1024) * 1024 + + # set memory limit + xc.domain_setmaxmem(dominfo.getDomid(), maxmem) + + balloon.free(memory + shadow) + + shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow / 1024) dominfo.info['shadow_memory'] = shadow_cur - - xc.domain_setmaxmem(dominfo.getDomid(), dominfo.getMemoryMaximum()) cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE), fd, dominfo.getDomid(), @@ -219,7 +230,7 @@ def restore(xd, fd, dominfo = None, paus forkHelper(cmd, fd, handler.handler, True) # We don't want to pass this fd to any other children -- we - # might need to recover ths disk space that backs it. + # might need to recover the disk space that backs it. try: flags = fcntl.fcntl(fd, fcntl.F_GETFD) flags |= fcntl.FD_CLOEXEC diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/XendConfig.py Thu Sep 06 12:05:15 2007 -0600 @@ -28,9 +28,9 @@ from xen.xend.XendDevices import XendDev from xen.xend.XendDevices import XendDevices from xen.xend.PrettyPrint import prettyprintstring from xen.xend.XendConstants import DOM_STATE_HALTED +from xen.xend.server.BlktapController import blktap_disk_types from xen.xend.server.netif import randomMAC from xen.util.blkif import blkdev_name_to_number -from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance from xen.util import xsconstants log = logging.getLogger("xend.XendConfig") @@ -433,7 +433,8 @@ class XendConfig(dict): self['cpu_time'] = dominfo['cpu_time']/1e9 if dominfo.get('ssidref'): ssidref = int(dominfo.get('ssidref')) - self['security_label'] = XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref) + import xen.util.xsm.xsm as security + self['security_label'] = security.ssidref2security_label(ssidref) self['shutdown_reason'] = dominfo['shutdown_reason'] @@ -651,7 +652,6 @@ class XendConfig(dict): # ['ssidref', 196611]] policy = "" label = "" - policytype = xsconstants.ACM_POLICY_ID for idx in range(0, len(secinfo)): if secinfo[idx][0] == "access_control": for aidx in range(1, len(secinfo[idx])): @@ -659,9 +659,10 @@ class XendConfig(dict): policy = secinfo[idx][aidx][1] if secinfo[idx][aidx][0] == "label": label = secinfo[idx][aidx][1] - if label != "" and policy != "": - cfg['security_label'] = "%s:%s:%s" % \ - (policytype, policy, label) + import xen.util.xsm.xsm as security + cfg['security_label'] = \ + security.set_security_label(policy, label) + if not sxp.child_value(sxp_cfg, 'security_label'): del cfg['security'] old_state = sxp.child_value(sxp_cfg, 'state') @@ -1084,6 +1085,11 @@ class XendConfig(dict): else: dev_info['driver'] = 'paravirtualised' + if dev_type == 'tap': + if dev_info['uname'].split(':')[1] not in blktap_disk_types: + raise XendConfigError("tap:%s not a valid disk type" % + dev_info['uname'].split(':')[1]) + if dev_type == 'vif': if not dev_info.get('mac'): dev_info['mac'] = randomMAC() diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Sep 06 12:05:15 2007 -0600 @@ -36,7 +36,7 @@ import xen.lowlevel.xc import xen.lowlevel.xc from xen.util import asserts from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype -from xen.util import security +import xen.util.xsm.xsm as security from xen.xend import balloon, sxp, uuid, image, arch, osdep from xen.xend import XendOptions, XendNode, XendConfig @@ -607,6 +607,9 @@ class XendDomainInfo: _, dev_info = sxprs[dev] else: # 'vbd' or 'tap' dev_info = self.getDeviceInfo_vbd(dev) + # To remove the UUID of the device from refs, + # deviceClass must be always 'vbd'. + deviceClass = 'vbd' if dev_info is None: return rc @@ -981,7 +984,7 @@ class XendDomainInfo: changed = True # Check if the rtc offset has changes - if vm_details.get("rtc/timeoffset", 0) != self.info["platform"].get("rtc_timeoffset", 0): + if vm_details.get("rtc/timeoffset", "0") != self.info["platform"].get("rtc_timeoffset", "0"): self.info["platform"]["rtc_timeoffset"] = vm_details.get("rtc/timeoffset", 0) changed = True @@ -1770,7 +1773,8 @@ class XendDomainInfo: self._cleanupVm() if self.dompath is not None: - xc.domain_destroy_hook(self.domid) + if self.domid is not None: + xc.domain_destroy_hook(self.domid) self.destroyDomain() self._cleanup_phantom_devs(paths) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/XendVDI.py --- a/tools/python/xen/xend/XendVDI.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/XendVDI.py Thu Sep 06 12:05:15 2007 -0600 @@ -23,7 +23,8 @@ import os from xen.util.xmlrpclib2 import stringify from xmlrpclib import dumps, loads -from xen.util import security, xsconstants +from xen.util import xsconstants +import xen.util.xsm.xsm as security from xen.xend.XendError import SecurityError KB = 1024 diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/XendXSPolicy.py --- a/tools/python/xen/xend/XendXSPolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/XendXSPolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -20,7 +20,8 @@ from xen.xend.XendBase import XendBase from xen.xend.XendBase import XendBase from xen.xend.XendError import * from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance -from xen.util import xsconstants, security +from xen.util import xsconstants +import xen.util.xsm.xsm as security import base64 log = logging.getLogger("xend.XendXSPolicy") diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/XendXSPolicyAdmin.py --- a/tools/python/xen/xend/XendXSPolicyAdmin.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/XendXSPolicyAdmin.py Thu Sep 06 12:05:15 2007 -0600 @@ -22,7 +22,8 @@ from xml.dom import minidom, Node from xen.xend.XendLogging import log from xen.xend import uuid -from xen.util import security, xsconstants, dictio, bootloader +from xen.util import xsconstants, dictio, bootloader +import xen.util.xsm.acm.acm as security from xen.util.xspolicy import XSPolicy from xen.util.acmpolicy import ACMPolicy from xen.xend.XendError import SecurityError diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/server/BlktapController.py --- a/tools/python/xen/xend/server/BlktapController.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/server/BlktapController.py Thu Sep 06 12:05:15 2007 -0600 @@ -6,6 +6,14 @@ from xen.xend.XendLogging import log phantomDev = 0; phantomId = 0; + +blktap_disk_types = [ + 'aio', + 'sync', + 'vmdk', + 'ram', + 'qcow' + ] class BlktapController(BlkifController): def __init__(self, vm): diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/server/blkif.py Thu Sep 06 12:05:15 2007 -0600 @@ -20,7 +20,7 @@ import string import string from xen.util import blkif -from xen.util import security +import xen.util.xsm.xsm as security from xen.xend.XendError import VmError from xen.xend.server.DevController import DevController diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xend/server/netif.py --- a/tools/python/xen/xend/server/netif.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xend/server/netif.py Thu Sep 06 12:05:15 2007 -0600 @@ -27,8 +27,8 @@ from xen.xend import XendOptions from xen.xend import XendOptions from xen.xend.server.DevController import DevController from xen.xend.XendError import VmError -from xen.util import security from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance +import xen.util.xsm.xsm as security from xen.xend.XendLogging import log diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/addlabel.py --- a/tools/python/xen/xm/addlabel.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/addlabel.py Thu Sep 06 12:05:15 2007 -0600 @@ -23,7 +23,7 @@ import sys import sys from xen.util import dictio -from xen.util import security +import xen.util.xsm.xsm as security from xen.xm.opts import OptionError from xen.util import xsconstants from xen.xm import main as xm_main diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/cfgbootpolicy.py --- a/tools/python/xen/xm/cfgbootpolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/cfgbootpolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -26,11 +26,11 @@ import shutil import shutil import string import re -from xen.util.security import err -from xen.util.security import policy_dir_prefix, xen_title_re -from xen.util.security import boot_filename, altboot_filename -from xen.util.security import any_title_re, xen_kernel_re, any_module_re -from xen.util.security import empty_line_re, binary_name_re, policy_name_re +from xen.util.xsm.xsm import err +from xen.util.xsm.xsm import policy_dir_prefix, xen_title_re +from xen.util.xsm.xsm import boot_filename, altboot_filename +from xen.util.xsm.xsm import any_title_re, xen_kernel_re, any_module_re +from xen.util.xsm.xsm import empty_line_re, binary_name_re, policy_name_re from xen.util import xsconstants from xen.xm.opts import OptionError from xen.xm import main as xm_main diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/create.py Thu Sep 06 12:05:15 2007 -0600 @@ -33,7 +33,7 @@ import xen.xend.XendClient import xen.xend.XendClient from xen.xend.XendBootloader import bootloader from xen.util import blkif -from xen.util import security +import xen.util.xsm.xsm as security from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm from xen.xm.opts import * @@ -725,7 +725,8 @@ def configure_hvm(config_image, vals): for a in args: if a in vals.__dict__ and vals.__dict__[a] is not None: config_image.append([a, vals.__dict__[a]]) - config_image.append(['vncpasswd', vals.vncpasswd]) + if vals.vncpasswd is not None: + config_image.append(['vncpasswd', vals.vncpasswd]) def make_config(vals): @@ -1220,7 +1221,7 @@ def config_security_check(config, verbos if verbose: print " %s: PERMITTED" % (resource) - except security.ACMError: + except security.XSMError: print " %s: DENIED" % (resource) (poltype, res_label, res_policy) = security.get_res_label(resource) if not res_label: @@ -1242,7 +1243,7 @@ def create_security_check(config): passed = 1 else: print "Checking resources: (skipped)" - except security.ACMError: + except security.XSMError: sys.exit(-1) return passed @@ -1299,7 +1300,7 @@ def main(argv): map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs) elif not opts.is_xml: if not create_security_check(config): - raise security.ACMError( + raise security.XSMError( 'Security Configuration prevents domain from starting') dom = make_domain(opts, config) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/dry-run.py --- a/tools/python/xen/xm/dry-run.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/dry-run.py Thu Sep 06 12:05:15 2007 -0600 @@ -19,7 +19,7 @@ """Tests the security settings for a domain and its resources. """ import sys -from xen.util import security +import xen.util.xsm.xsm as security from xen.xm import create from xen.xend import sxp from xen.xm.opts import OptionError diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/dumppolicy.py --- a/tools/python/xen/xm/dumppolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/dumppolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -18,7 +18,7 @@ """Display currently enforced policy (low-level hypervisor representation). """ import sys -from xen.util.security import ACMError, err, dump_policy +from xen.util.xsm.xsm import XSMError, err, dump_policy from xen.xm.opts import OptionError def help(): diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/getlabel.py --- a/tools/python/xen/xm/getlabel.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/getlabel.py Thu Sep 06 12:05:15 2007 -0600 @@ -20,7 +20,7 @@ """ import sys, os, re from xen.util import dictio -from xen.util import security +import xen.util.xsm.xsm as security from xen.util import xsconstants from xen.xm.opts import OptionError from xen.xm import main as xm_main @@ -62,7 +62,7 @@ def get_resource_label(resource): "Please relabel the resource.") print policytype+":"+policy+":"+label else: - raise security.ACMError("Resource not labeled") + raise security.XSMError("Resource not labeled") def get_domain_label(configfile): @@ -95,7 +95,7 @@ def get_domain_label(configfile): # send error message if we didn't find anything if acline == "": - raise security.ACMError("Domain not labeled") + raise security.XSMError("Domain not labeled") # print out the label (title, data) = acline.split("=", 1) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/labels.py --- a/tools/python/xen/xm/labels.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/labels.py Thu Sep 06 12:05:15 2007 -0600 @@ -21,8 +21,8 @@ import sys import sys import traceback import string -from xen.util.security import ACMError, err, list_labels, active_policy -from xen.util.security import vm_label_re, res_label_re, all_label_re +from xen.util.xsm.xsm import XSMError, err, list_labels, active_policy +from xen.util.xsm.xsm import vm_label_re, res_label_re, all_label_re from xen.xm.opts import OptionError from xen.util.acmpolicy import ACMPolicy from xen.util import xsconstants @@ -78,7 +78,7 @@ def labels(policy, ptype): for label in labels: print label - except ACMError: + except XSMError: sys.exit(-1) except: traceback.print_exc(limit = 1) diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/loadpolicy.py --- a/tools/python/xen/xm/loadpolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/loadpolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -20,7 +20,7 @@ """ import sys import traceback -from xen.util.security import ACMError, err, load_policy +from xen.util.xsm.xsm import XSMError, err, load_policy from xen.xm.opts import OptionError from xen.xm import main as xm_main from xen.util import xsconstants diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/main.py Thu Sep 06 12:05:15 2007 -0600 @@ -49,7 +49,8 @@ from xen.xm.opts import OptionError, Opt from xen.xm.opts import OptionError, Opts, wrap, set_true from xen.xm import console from xen.util.xmlrpcclient import ServerProxy -from xen.util.security import ACMError +import xen.util.xsm.xsm as security +from xen.util.xsm.xsm import XSMError from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY import XenAPI @@ -872,12 +873,7 @@ def parse_doms_info(info): } security_label = get_info('security_label', str, '') - tmp = security_label.split(":") - if len(tmp) != 3: - seclabel = "" - else: - seclabel = security_label - parsed_info['seclabel'] = seclabel + parsed_info['seclabel'] = security.parse_security_label(security_label) if serverType == SERVER_XEN_API: parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024 @@ -935,14 +931,14 @@ def xm_brief_list(doms): print format % d def xm_label_list(doms): - print '%-32s %5s %5s %5s %10s %9s %-8s' % \ + print '%-40s %3s %5s %5s %10s %9s %-10s' % \ ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label') - + output = [] - format = '%(name)-32s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \ - '%(cpu_time)8.1f %(seclabel)9s' - - from xen.util import security + format = '%(name)-40s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \ + '%(cpu_time)8.1f %(seclabel)10s' + + import xen.util.xsm.xsm as security for dom in doms: d = parse_doms_info(dom) @@ -2580,12 +2576,12 @@ def _run_cmd(cmd, cmd_name, args): print e.usage except XenAPIUnsupportedException, e: err(str(e)) - except ACMError, e: + except XSMError, e: err(str(e)) except Exception, e: if serverType != SERVER_XEN_API: - from xen.util import security - if isinstance(e, security.ACMError): + import xen.util.xsm.xsm as security + if isinstance(e, security.XSMError): err(str(e)) return False, 1 print "Unexpected error:", sys.exc_info()[0] diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/makepolicy.py --- a/tools/python/xen/xm/makepolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/makepolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -19,7 +19,7 @@ """ import sys import traceback -from xen.util.security import ACMError, err, make_policy +from xen.util.xsm.xsm import ACMError, err, make_policy from xen.util import xsconstants from xen.xm.opts import OptionError from xen.xm import main as xm_main diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/resources.py --- a/tools/python/xen/xm/resources.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/resources.py Thu Sep 06 12:05:15 2007 -0600 @@ -20,7 +20,7 @@ """ import sys from xen.util import dictio -from xen.util import security +import xen.util.xsm.xsm as security from xen.util import xsconstants from xen.xm.opts import OptionError from xen.xm import main as xm_main diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/rmlabel.py --- a/tools/python/xen/xm/rmlabel.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/rmlabel.py Thu Sep 06 12:05:15 2007 -0600 @@ -20,7 +20,7 @@ """ import sys, os, re from xen.util import dictio -from xen.util import security +import xen.util.xsm.xsm as security from xen.xm.opts import OptionError from xen.xm import main as xm_main from xen.xm.main import server @@ -108,7 +108,7 @@ def rm_domain_label(configfile): # send error message if we didn't find anything to remove if not removed: - raise security.ACMError('Domain not labeled') + raise security.XSMError('Domain not labeled') # write the data back out to the file fd = open(fil, "wb") diff -r 12be90e2f831 -r 4ffca478e2f7 tools/python/xen/xm/setpolicy.py --- a/tools/python/xen/xm/setpolicy.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/python/xen/xm/setpolicy.py Thu Sep 06 12:05:15 2007 -0600 @@ -26,7 +26,7 @@ from xen.util import xsconstants from xen.util import xsconstants from xen.util.acmpolicy import ACMPolicy from xen.xm.opts import OptionError -from xen.util.security import policy_dir_prefix +from xen.util.xsm.acm.acm import policy_dir_prefix from xen.xm import main as xm_main from xen.xm.main import server diff -r 12be90e2f831 -r 4ffca478e2f7 tools/security/secpol_tool.c --- a/tools/security/secpol_tool.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/security/secpol_tool.c Thu Sep 06 12:05:15 2007 -0600 @@ -34,8 +34,8 @@ #include <string.h> #include <netinet/in.h> #include <stdint.h> -#include <xen/acm.h> -#include <xen/acm_ops.h> +#include <xen/xsm/acm.h> +#include <xen/xsm/acm_ops.h> #include <xenctrl.h> diff -r 12be90e2f831 -r 4ffca478e2f7 tools/security/secpol_xml2bin.c --- a/tools/security/secpol_xml2bin.c Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/security/secpol_xml2bin.c Thu Sep 06 12:05:15 2007 -0600 @@ -22,6 +22,7 @@ * * indent -i4 -kr -nut */ + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -38,7 +39,7 @@ #include <libxml/tree.h> #include <libxml/xmlreader.h> #include <stdint.h> -#include <xen/acm.h> +#include <xen/xsm/acm.h> #include "secpol_xml2bin.h" diff -r 12be90e2f831 -r 4ffca478e2f7 tools/xm-test/lib/XmTestLib/acm.py --- a/tools/xm-test/lib/XmTestLib/acm.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/xm-test/lib/XmTestLib/acm.py Thu Sep 06 12:05:15 2007 -0600 @@ -18,7 +18,7 @@ """ from Test import * -from xen.util import security +import xen.util.xsm.xsm as security from xen.xm.main import server from xen.util import xsconstants import re diff -r 12be90e2f831 -r 4ffca478e2f7 tools/xm-test/tests/security-acm/01_security-acm_basic.py --- a/tools/xm-test/tests/security-acm/01_security-acm_basic.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/xm-test/tests/security-acm/01_security-acm_basic.py Thu Sep 06 12:05:15 2007 -0600 @@ -14,7 +14,7 @@ # - resources from XmTestLib import * -from xen.util import security +import xen.util.xsm.xsm as security from xen.util import xsconstants import commands import os diff -r 12be90e2f831 -r 4ffca478e2f7 tools/xm-test/tests/security-acm/07_security-acm_pol_update.py --- a/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/xm-test/tests/security-acm/07_security-acm_pol_update.py Thu Sep 06 12:05:15 2007 -0600 @@ -9,7 +9,8 @@ from XmTestLib.XenAPIDomain import XmTes from XmTestLib.XenAPIDomain import XmTestAPIDomain from XmTestLib import * from xen.xend import XendAPIConstants -from xen.util import acmpolicy, security, xsconstants +import xen.util.xsm.xsm as security +from xen.util import acmpolicy, xsconstants from xen.util.acmpolicy import ACMPolicy from xen.xend.XendDomain import DOM0_UUID from XmTestLib.acm import * diff -r 12be90e2f831 -r 4ffca478e2f7 tools/xm-test/tests/security-acm/08_security-acm_xapi.py --- a/tools/xm-test/tests/security-acm/08_security-acm_xapi.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/xm-test/tests/security-acm/08_security-acm_xapi.py Thu Sep 06 12:05:15 2007 -0600 @@ -9,7 +9,8 @@ from XmTestLib.XenAPIDomain import XmTes from XmTestLib.XenAPIDomain import XmTestAPIDomain from XmTestLib import * from xen.xend import XendAPIConstants -from xen.util import acmpolicy, security, xsconstants +import xen.util.xsm.xsm as security +from xen.util import acmpolicy, xsconstants import commands import os diff -r 12be90e2f831 -r 4ffca478e2f7 tools/xm-test/tests/security-acm/09_security-acm_pol_update.py --- a/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py Thu Sep 06 09:05:26 2007 -0600 +++ b/tools/xm-test/tests/security-acm/09_security-acm_pol_update.py Thu Sep 06 12:05:15 2007 -0600 @@ -10,7 +10,8 @@ from XmTestLib.acm import * from XmTestLib.acm import * from XmTestLib import * from xen.xend import XendAPIConstants -from xen.util import security, xsconstants +import xen.util.xsm.xsm as security +from xen.util import xsconstants from xen.util.acmpolicy import ACMPolicy from xen.xend.XendDomain import DOM0_UUID import base64 diff -r 12be90e2f831 -r 4ffca478e2f7 unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h --- a/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Thu Sep 06 09:05:26 2007 -0600 +++ b/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Thu Sep 06 12:05:15 2007 -0600 @@ -108,12 +108,21 @@ extern char *kasprintf(gfp_t gfp, const #endif #if defined(_LINUX_NETDEVICE_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -#define netif_tx_lock_bh(dev) (spin_lock_bh(&(dev)->xmit_lock)) -#define netif_tx_unlock_bh(dev) (spin_unlock_bh(&(dev)->xmit_lock)) +#define netif_tx_lock_bh(dev) spin_lock_bh(&(dev)->xmit_lock) +#define netif_tx_unlock_bh(dev) spin_unlock_bh(&(dev)->xmit_lock) #endif #if defined(__LINUX_SEQLOCK_H) && !defined(DEFINE_SEQLOCK) #define DEFINE_SEQLOCK(x) seqlock_t x = SEQLOCK_UNLOCKED #endif +/* Bug in RHEL4-U3: rw_lock_t is mistakenly defined in DEFINE_RWLOCK() macro */ +#if defined(__LINUX_SPINLOCK_H) && defined(DEFINE_RWLOCK) +#define rw_lock_t rwlock_t #endif + +#if defined(__LINUX_SPINLOCK_H) && !defined(DEFINE_RWLOCK) +#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED +#endif + +#endif diff -r 12be90e2f831 -r 4ffca478e2f7 xen/Makefile --- a/xen/Makefile Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -1,7 +1,7 @@ # This is the correct place to edit the build version. # All other places this is stored (eg. compile.h) should be autogenerated. export XEN_VERSION = 3 -export XEN_SUBVERSION = 0 +export XEN_SUBVERSION = 2 export XEN_EXTRAVERSION ?= -unstable$(XEN_VENDORVERSION) export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) -include xen-version @@ -55,7 +55,7 @@ _clean: delete-unfresh-files $(MAKE) -f $(BASEDIR)/Rules.mk -C include clean $(MAKE) -f $(BASEDIR)/Rules.mk -C common clean $(MAKE) -f $(BASEDIR)/Rules.mk -C drivers clean - $(MAKE) -f $(BASEDIR)/Rules.mk -C acm clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean rm -f include/asm *.o $(TARGET)* *~ core rm -f include/asm-*/asm-offsets.h @@ -122,7 +122,7 @@ build-headers: build-headers: $(MAKE) -C include/public/foreign -SUBDIRS = acm arch/$(TARGET_ARCH) common drivers +SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers define all_sources ( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \ find include -name 'asm-*' -prune -o -name '*.h' -print; \ diff -r 12be90e2f831 -r 4ffca478e2f7 xen/Rules.mk --- a/xen/Rules.mk Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/Rules.mk Thu Sep 06 12:05:15 2007 -0600 @@ -52,11 +52,14 @@ HDRS := $(filter-out %/asm-offsets.h,$( # Note that link order matters! ALL_OBJS-y += $(BASEDIR)/common/built_in.o ALL_OBJS-y += $(BASEDIR)/drivers/built_in.o -ALL_OBJS-$(ACM_SECURITY) += $(BASEDIR)/acm/built_in.o +ALL_OBJS-y += $(BASEDIR)/xsm/built_in.o ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o CFLAGS-y += -g -D__XEN__ -CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY +CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE +CFLAGS-$(FLASK_ENABLE) += -DFLASK_ENABLE -DXSM_MAGIC=0xf97cff8c +CFLAGS-$(FLASK_ENABLE) += -DFLASK_DEVELOP -DFLASK_BOOTPARAM -DFLASK_AVC_STATS +CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY -DXSM_MAGIC=0xbcde0100 CFLAGS-$(verbose) += -DVERBOSE CFLAGS-$(crash_debug) += -DCRASH_DEBUG CFLAGS-$(perfc) += -DPERF_COUNTERS diff -r 12be90e2f831 -r 4ffca478e2f7 xen/acm/Makefile --- a/xen/acm/Makefile Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -obj-y += acm_core.o -obj-y += acm_policy.o -obj-y += acm_simple_type_enforcement_hooks.o -obj-y += acm_chinesewall_hooks.o -obj-y += acm_null_hooks.o diff -r 12be90e2f831 -r 4ffca478e2f7 xen/acm/acm_chinesewall_hooks.c --- a/xen/acm/acm_chinesewall_hooks.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -/**************************************************************** - * acm_chinesewall_hooks.c - * - * Copyright (C) 2005 IBM Corporation - * - * Author: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * - * Contributions: - * Stefan Berger <stefanb@xxxxxxxxxxxxxx> - * - * 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, version 2 of the - * License. - * - * sHype Chinese Wall Policy for Xen - * This code implements the hooks that are called - * throughout Xen operations and decides authorization - * based on domain types and Chinese Wall conflict type - * sets. The CHWALL policy decides if a new domain can be started - * based on the types of running domains and the type of the - * new domain to be started. If the new domain's type is in - * conflict with types of running domains, then this new domain - * is not allowed to be created. A domain can have multiple types, - * in which case all types of a new domain must be conflict-free - * with all types of already running domains. - * - * indent -i4 -kr -nut - * - */ - -#include <xen/config.h> -#include <xen/errno.h> -#include <xen/types.h> -#include <xen/lib.h> -#include <xen/delay.h> -#include <xen/sched.h> -#include <public/acm.h> -#include <asm/atomic.h> -#include <acm/acm_core.h> -#include <acm/acm_hooks.h> -#include <acm/acm_endian.h> -#include <acm/acm_core.h> - -ssidref_t dom0_chwall_ssidref = 0x0001; - -/* local cache structures for chinese wall policy */ -struct chwall_binary_policy chwall_bin_pol; - -/* - * Initializing chinese wall policy (will be filled by policy partition - * using setpolicy command) - */ -int acm_init_chwall_policy(void) -{ - /* minimal startup policy; policy write-locked already */ - chwall_bin_pol.max_types = 1; - chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref; - chwall_bin_pol.max_conflictsets = 1; - chwall_bin_pol.ssidrefs = - (domaintype_t *) xmalloc_array(domaintype_t, - chwall_bin_pol.max_ssidrefs * - chwall_bin_pol.max_types); - chwall_bin_pol.conflict_sets = - (domaintype_t *) xmalloc_array(domaintype_t, - chwall_bin_pol.max_conflictsets * - chwall_bin_pol.max_types); - chwall_bin_pol.running_types = - (domaintype_t *) xmalloc_array(domaintype_t, - chwall_bin_pol.max_types); - chwall_bin_pol.conflict_aggregate_set = - (domaintype_t *) xmalloc_array(domaintype_t, - chwall_bin_pol.max_types); - - if ( (chwall_bin_pol.conflict_sets == NULL) - || (chwall_bin_pol.running_types == NULL) - || (chwall_bin_pol.ssidrefs == NULL) - || (chwall_bin_pol.conflict_aggregate_set == NULL) ) - return ACM_INIT_SSID_ERROR; - - /* initialize state */ - memset((void *) chwall_bin_pol.ssidrefs, 0, - chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types * - sizeof(domaintype_t)); - memset((void *) chwall_bin_pol.conflict_sets, 0, - chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types * - sizeof(domaintype_t)); - memset((void *) chwall_bin_pol.running_types, 0, - chwall_bin_pol.max_types * sizeof(domaintype_t)); - memset((void *) chwall_bin_pol.conflict_aggregate_set, 0, - chwall_bin_pol.max_types * sizeof(domaintype_t)); - return ACM_OK; -} - - -static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref) -{ - struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid); - traceprintk("%s.\n", __func__); - - if ( chwall_ssidp == NULL ) - return ACM_INIT_SSID_ERROR; - - chwall_ssidp->chwall_ssidref = - GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); - - if ( chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs ) - { - printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset " - "(0).\n", - __func__, chwall_ssidp->chwall_ssidref); - xfree(chwall_ssidp); - return ACM_INIT_SSID_ERROR; - } - (*chwall_ssid) = chwall_ssidp; - printkd("%s: determined chwall_ssidref to %x.\n", - __func__, chwall_ssidp->chwall_ssidref); - return ACM_OK; -} - - -static void chwall_free_domain_ssid(void *chwall_ssid) -{ - xfree(chwall_ssid); - return; -} - - -/* dump chinese wall cache; policy read-locked already */ -static int chwall_dump_policy(u8 * buf, u32 buf_size) -{ - struct acm_chwall_policy_buffer *chwall_buf = - (struct acm_chwall_policy_buffer *) buf; - int ret = 0; - - if ( buf_size < sizeof(struct acm_chwall_policy_buffer) ) - return -EINVAL; - - chwall_buf->chwall_max_types = cpu_to_be32(chwall_bin_pol.max_types); - chwall_buf->chwall_max_ssidrefs = cpu_to_be32(chwall_bin_pol.max_ssidrefs); - chwall_buf->policy_code = cpu_to_be32(ACM_CHINESE_WALL_POLICY); - chwall_buf->chwall_ssid_offset = - cpu_to_be32(sizeof(struct acm_chwall_policy_buffer)); - chwall_buf->chwall_max_conflictsets = - cpu_to_be32(chwall_bin_pol.max_conflictsets); - chwall_buf->chwall_conflict_sets_offset = - cpu_to_be32(be32_to_cpu(chwall_buf->chwall_ssid_offset) + - sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs * - chwall_bin_pol.max_types); - chwall_buf->chwall_running_types_offset = - cpu_to_be32(be32_to_cpu(chwall_buf->chwall_conflict_sets_offset) + - sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets * - chwall_bin_pol.max_types); - chwall_buf->chwall_conflict_aggregate_offset = - cpu_to_be32(be32_to_cpu(chwall_buf->chwall_running_types_offset) + - sizeof(domaintype_t) * chwall_bin_pol.max_types); - - ret = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset) + - sizeof(domaintype_t) * chwall_bin_pol.max_types; - - ret = (ret + 7) & ~7; - - if ( buf_size < ret ) - return -EINVAL; - - /* now copy buffers over */ - arrcpy16((u16 *) (buf + be32_to_cpu(chwall_buf->chwall_ssid_offset)), - chwall_bin_pol.ssidrefs, - chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types); - - arrcpy16((u16 *) (buf + - be32_to_cpu(chwall_buf->chwall_conflict_sets_offset)), - chwall_bin_pol.conflict_sets, - chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types); - - arrcpy16((u16 *) (buf + - be32_to_cpu(chwall_buf->chwall_running_types_offset)), - chwall_bin_pol.running_types, chwall_bin_pol.max_types); - - arrcpy16((u16 *) (buf + - be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset)), - chwall_bin_pol.conflict_aggregate_set, - chwall_bin_pol.max_types); - return ret; -} - -/* - * Adapt security state (running_types and conflict_aggregate_set) to all - * running domains; chwall_init_state is called when a policy is changed - * to bring the security information into a consistent state and to detect - * violations (return != 0) from a security point of view, we simulate - * that all running domains are re-started - */ -static int -chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf, - domaintype_t * ssidrefs, - domaintype_t * conflict_sets, - domaintype_t * running_types, - domaintype_t * conflict_aggregate_set, - struct acm_sized_buffer *errors /* may be NULL */) -{ - int violation = 0, i, j; - struct chwall_ssid *chwall_ssid; - ssidref_t chwall_ssidref; - struct acm_ssid_domain *rawssid; - - read_lock(&ssid_list_rwlock); - - /* go through all domains and adjust policy as if this domain was - * started now - */ - for_each_acmssid( rawssid ) - { - chwall_ssid = - GET_SSIDP(ACM_CHINESE_WALL_POLICY, rawssid); - chwall_ssidref = chwall_ssid->chwall_ssidref; - traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n", - __func__, d->domain_id, chwall_ssidref); - /* a) adjust types ref-count for running domains */ - for ( i = 0; i < chwall_buf->chwall_max_types; i++ ) - running_types[i] += - ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i]; - - /* b) check for conflict */ - for ( i = 0; i < chwall_buf->chwall_max_types; i++ ) - if ( conflict_aggregate_set[i] && - ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i] ) - { - printk("%s: CHINESE WALL CONFLICT in type %02x.\n", - __func__, i); - violation = 1; - - acm_array_append_tuple(errors, ACM_CHWALL_CONFLICT, i); - - goto out; - } - - /* set violation and break out of the loop */ - /* c) adapt conflict aggregate set for this domain - * (notice conflicts) - */ - for ( i = 0; i < chwall_buf->chwall_max_conflictsets; i++ ) - { - int common = 0; - /* check if conflict_set_i and ssidref have common types */ - for ( j = 0; j < chwall_buf->chwall_max_types; j++ ) - if ( conflict_sets[i * chwall_buf->chwall_max_types + j] && - ssidrefs[chwall_ssidref * - chwall_buf->chwall_max_types + j] ) - { - common = 1; - break; - } - - if ( common == 0 ) - continue; /* try next conflict set */ - - /* now add types of the conflict set to conflict_aggregate_set - * (except types in chwall_ssidref) - */ - for ( j = 0; j < chwall_buf->chwall_max_types; j++ ) - if ( conflict_sets[i * chwall_buf->chwall_max_types + j] && - !ssidrefs[chwall_ssidref * - chwall_buf->chwall_max_types + j] ) - conflict_aggregate_set[j]++; - } - } - out: - read_unlock(&ssid_list_rwlock); - return violation; - /* returning "violation != 0" means that the currently running set of - * domains would not be possible if the new policy had been enforced - * before starting them; for chinese wall, this means that the new - * policy includes at least one conflict set of which more than one - * type is currently running - */ -} - - -int -do_chwall_init_state_curr(struct acm_sized_buffer *errors) -{ - struct acm_chwall_policy_buffer chwall_buf = - { - /* only these two are important */ - .chwall_max_types = chwall_bin_pol.max_types, - .chwall_max_conflictsets = chwall_bin_pol.max_conflictsets, - }; - /* reset running_types and aggregate set for recalculation */ - memset(chwall_bin_pol.running_types, - 0x0, - sizeof(domaintype_t) * chwall_bin_pol.max_types); - memset(chwall_bin_pol.conflict_aggregate_set, - 0x0, - sizeof(domaintype_t) * chwall_bin_pol.max_types); - return chwall_init_state(&chwall_buf, - chwall_bin_pol.ssidrefs, - chwall_bin_pol.conflict_sets, - chwall_bin_pol.running_types, - chwall_bin_pol.conflict_aggregate_set, - errors); -} - -/* - * Attempt to set the policy. This function must be called in test_only - * mode first to only perform checks. A second call then does the - * actual changes. - */ -static int _chwall_update_policy(u8 *buf, u32 buf_size, int test_only, - struct acm_sized_buffer *errors) -{ - int rc = -EFAULT; - /* policy write-locked already */ - struct acm_chwall_policy_buffer *chwall_buf = - (struct acm_chwall_policy_buffer *) buf; - void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, - *conflict_aggregate_set = NULL; - - /* 1. allocate new buffers */ - ssids = - xmalloc_array(domaintype_t, - chwall_buf->chwall_max_types * - chwall_buf->chwall_max_ssidrefs); - conflict_sets = - xmalloc_array(domaintype_t, - chwall_buf->chwall_max_conflictsets * - chwall_buf->chwall_max_types); - running_types = - xmalloc_array(domaintype_t, chwall_buf->chwall_max_types); - conflict_aggregate_set = - xmalloc_array(domaintype_t, chwall_buf->chwall_max_types); - - if ( (ssids == NULL) || (conflict_sets == NULL) || - (running_types == NULL) || (conflict_aggregate_set == NULL) ) - goto error_free; - - /* 2. set new policy */ - if ( chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) * - chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs > - buf_size ) - goto error_free; - - arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset, - sizeof(domaintype_t), - chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs); - - if ( chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) * - chwall_buf->chwall_max_types * - chwall_buf->chwall_max_conflictsets > buf_size ) - goto error_free; - - arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset, - sizeof(domaintype_t), - chwall_buf->chwall_max_types * - chwall_buf->chwall_max_conflictsets); - - /* we also use new state buffers since max_types can change */ - memset(running_types, 0, - sizeof(domaintype_t) * chwall_buf->chwall_max_types); - memset(conflict_aggregate_set, 0, - sizeof(domaintype_t) * chwall_buf->chwall_max_types); - - /* 3. now re-calculate the state for the new policy based on - * running domains; this can fail if new policy is conflicting - * with running domains - */ - if ( chwall_init_state(chwall_buf, ssids, - conflict_sets, running_types, - conflict_aggregate_set, - errors)) - { - printk("%s: New policy conflicts with running domains. Policy load aborted.\n", - __func__); - goto error_free; /* new policy conflicts with running domains */ - } - - /* if this was only a test run, exit with ACM_OK */ - if ( test_only ) - { - rc = ACM_OK; - goto error_free; - } - - /* 4. free old policy buffers, replace with new ones */ - chwall_bin_pol.max_types = chwall_buf->chwall_max_types; - chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs; - chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets; - xfree(chwall_bin_pol.ssidrefs); - xfree(chwall_bin_pol.conflict_aggregate_set); - xfree(chwall_bin_pol.running_types); - xfree(chwall_bin_pol.conflict_sets); - chwall_bin_pol.ssidrefs = ssids; - chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set; - chwall_bin_pol.running_types = running_types; - chwall_bin_pol.conflict_sets = conflict_sets; - - return ACM_OK; - - error_free: - if ( !test_only ) - printk("%s: ERROR setting policy.\n", __func__); - - xfree(ssids); - xfree(conflict_sets); - xfree(running_types); - xfree(conflict_aggregate_set); - return rc; -} - -/* - * This function MUST be called before the chwall_ste_policy function! - */ -static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy, - struct acm_sized_buffer *errors) -{ - struct acm_chwall_policy_buffer *chwall_buf = - (struct acm_chwall_policy_buffer *) buf; - - if ( buf_size < sizeof(struct acm_chwall_policy_buffer) ) - return -EINVAL; - - /* rewrite the policy due to endianess */ - chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code); - chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version); - chwall_buf->chwall_max_types = - be32_to_cpu(chwall_buf->chwall_max_types); - chwall_buf->chwall_max_ssidrefs = - be32_to_cpu(chwall_buf->chwall_max_ssidrefs); - chwall_buf->chwall_max_conflictsets = - be32_to_cpu(chwall_buf->chwall_max_conflictsets); - chwall_buf->chwall_ssid_offset = - be32_to_cpu(chwall_buf->chwall_ssid_offset); - chwall_buf->chwall_conflict_sets_offset = - be32_to_cpu(chwall_buf->chwall_conflict_sets_offset); - chwall_buf->chwall_running_types_offset = - be32_to_cpu(chwall_buf->chwall_running_types_offset); - chwall_buf->chwall_conflict_aggregate_offset = - be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset); - - /* policy type and version checks */ - if ( (chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) || - (chwall_buf->policy_version != ACM_CHWALL_VERSION) ) - return -EINVAL; - - /* during boot dom0_chwall_ssidref is set */ - if ( is_bootpolicy && - (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs) ) - return -EINVAL; - - return _chwall_update_policy(buf, buf_size, 1, errors); -} - -static int chwall_set_policy(u8 *buf, u32 buf_size) -{ - return _chwall_update_policy(buf, buf_size, 0, NULL); -} - -static int chwall_dump_stats(u8 * buf, u16 len) -{ - /* no stats for Chinese Wall Policy */ - return 0; -} - -static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len) -{ - int i; - - /* fill in buffer */ - if ( chwall_bin_pol.max_types > len ) - return -EFAULT; - - if ( ssidref >= chwall_bin_pol.max_ssidrefs ) - return -EFAULT; - - /* read types for chwall ssidref */ - for ( i = 0; i < chwall_bin_pol.max_types; i++ ) - { - if ( chwall_bin_pol. - ssidrefs[ssidref * chwall_bin_pol.max_types + i] ) - buf[i] = 1; - else - buf[i] = 0; - } - return chwall_bin_pol.max_types; -} - -/*************************** - * Authorization functions - ***************************/ - -/* -------- DOMAIN OPERATION HOOKS -----------*/ - -static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref) -{ - ssidref_t chwall_ssidref; - int i, j; - - chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); - - if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs ) - { - printk("%s: ERROR chwall_ssidref > max(%x).\n", - __func__, chwall_bin_pol.max_ssidrefs - 1); - return ACM_ACCESS_DENIED; - } - - /* A: chinese wall check for conflicts */ - for ( i = 0; i < chwall_bin_pol.max_types; i++ ) - if ( chwall_bin_pol.conflict_aggregate_set[i] && - chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + i] ) - { - printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i); - return ACM_ACCESS_DENIED; - } - - /* B: chinese wall conflict set adjustment (so that other - * other domains simultaneously created are evaluated against - * this new set) - */ - for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) - { - int common = 0; - /* check if conflict_set_i and ssidref have common types */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j] ) - { - common = 1; - break; - } - if ( common == 0 ) - continue; /* try next conflict set */ - /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && !chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j]) - chwall_bin_pol.conflict_aggregate_set[j]++; - } - return ACM_ACCESS_PERMITTED; -} - - -static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref) -{ - int i, j; - ssidref_t chwall_ssidref; - - chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); - /* adjust types ref-count for running domains */ - for ( i = 0; i < chwall_bin_pol.max_types; i++ ) - chwall_bin_pol.running_types[i] += - chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + i]; - if ( domid ) - return; - - /* Xen does not call pre-create hook for DOM0; - * to consider type conflicts of any domain with DOM0, we need - * to adjust the conflict_aggregate for DOM0 here the same way it - * is done for non-DOM0 domains in the pre-hook */ - printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n", - __func__, ssidref, chwall_ssidref); - - /* chinese wall conflict set adjustment (so that other - * other domains simultaneously created are evaluated against this new set)*/ - for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) - { - int common = 0; - /* check if conflict_set_i and ssidref have common types */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j] ) - { - common = 1; - break; - } - - if ( common == 0 ) - { - /* try next conflict set */ - continue; - } - - /* now add types of the conflict set to conflict_aggregate_set - (except types in chwall_ssidref) */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && !chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j] ) - chwall_bin_pol.conflict_aggregate_set[j]++; - } - return; -} - - -/* - * To be called when creating a domain. If this call is unsuccessful, - * no state changes have occurred (adjustments of counters etc.). If it - * was successful, state was changed and can be undone using - * chwall_domain_destroy. - */ -static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref, - domid_t domid) -{ - int rc; - read_lock(&acm_bin_pol_rwlock); - - rc = _chwall_pre_domain_create(subject_ssid, ssidref); - if ( rc == ACM_ACCESS_PERMITTED ) - _chwall_post_domain_create(domid, ssidref); - - read_unlock(&acm_bin_pol_rwlock); - return rc; -} - -/* - * This function undoes everything a successful call to - * chwall_domain_create has done. - */ -static void chwall_domain_destroy(void *object_ssid, struct domain *d) -{ - int i, j; - struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY, - (struct acm_ssid_domain *) - object_ssid); - ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref; - - read_lock(&acm_bin_pol_rwlock); - - /* adjust running types set */ - for ( i = 0; i < chwall_bin_pol.max_types; i++ ) - chwall_bin_pol.running_types[i] -= - chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + i]; - - /* roll-back: re-adjust conflicting types aggregate */ - for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) - { - int common = 0; - /* check if conflict_set_i and ssidref have common types */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol.conflict_sets[i * chwall_bin_pol.max_types + j] - && chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j]) - { - common = 1; - break; - } - if ( common == 0 ) - { - /* try next conflict set, this one does not include - any type of chwall_ssidref */ - continue; - } - - /* now add types of the conflict set to conflict_aggregate_set - (except types in chwall_ssidref) */ - for ( j = 0; j < chwall_bin_pol.max_types; j++ ) - if ( chwall_bin_pol. - conflict_sets[i * chwall_bin_pol.max_types + j] - && !chwall_bin_pol.ssidrefs[chwall_ssidref * - chwall_bin_pol.max_types + j]) - chwall_bin_pol.conflict_aggregate_set[j]--; - } - - read_unlock(&acm_bin_pol_rwlock); - - return; -} - - -static int chwall_is_default_policy(void) -{ - return ( (chwall_bin_pol.max_types == 1 ) && - (chwall_bin_pol.max_ssidrefs == 2 ) ); -} - -struct acm_operations acm_chinesewall_ops = { - /* policy management services */ - .init_domain_ssid = chwall_init_domain_ssid, - .free_domain_ssid = chwall_free_domain_ssid, - .dump_binary_policy = chwall_dump_policy, - .test_binary_policy = chwall_test_policy, - .set_binary_policy = chwall_set_policy, - .dump_statistics = chwall_dump_stats, - .dump_ssid_types = chwall_dump_ssid_types, - /* domain management control hooks */ - .domain_create = chwall_domain_create, - .domain_destroy = chwall_domain_destroy, - /* event channel control hooks */ - .pre_eventchannel_unbound = NULL, - .fail_eventchannel_unbound = NULL, - .pre_eventchannel_interdomain = NULL, - .fail_eventchannel_interdomain = NULL, - /* grant table control hooks */ - .pre_grant_map_ref = NULL, - .fail_grant_map_ref = NULL, - .pre_grant_setup = NULL, - .fail_grant_setup = NULL, - /* generic domain-requested decision hooks */ - .sharing = NULL, - .authorization = NULL, - - .is_default_policy = chwall_is_default_policy, -}; - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 12be90e2f831 -r 4ffca478e2f7 xen/acm/acm_core.c --- a/xen/acm/acm_core.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,392 +0,0 @@ -/**************************************************************** - * acm_core.c - * - * Copyright (C) 2005 IBM Corporation - * - * Author: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * - * Contributors: - * Stefan Berger <stefanb@xxxxxxxxxxxxxx> - * - * 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, version 2 of the - * License. - * - * sHype access control module (ACM) - * This file handles initialization of the ACM - * as well as initializing/freeing security - * identifiers for domains (it calls on active - * policy hook functions). - * - */ - -#include <xen/config.h> -#include <xen/errno.h> -#include <xen/types.h> -#include <xen/lib.h> -#include <xen/delay.h> -#include <xen/sched.h> -#include <xen/multiboot.h> -#include <acm/acm_hooks.h> -#include <acm/acm_endian.h> - -/* debug: - * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE; - * define/undefine this constant to receive / suppress any - * security hook debug output of sHype - * - * include/public/acm.h defines a constant ACM_DEBUG - * define/undefine this constant to receive non-hook-related - * debug output. - */ - -/* function prototypes */ -void acm_init_chwall_policy(void); -void acm_init_ste_policy(void); - -extern struct acm_operations acm_chinesewall_ops, - acm_simple_type_enforcement_ops, acm_null_ops; - -/* global ACM policy (now dynamically determined at boot time) */ -u16 acm_active_security_policy = ACM_POLICY_UNDEFINED; - -/* global ops structs called by the hooks */ -struct acm_operations *acm_primary_ops = NULL; -/* called in hook if-and-only-if primary succeeds */ -struct acm_operations *acm_secondary_ops = NULL; - -/* acm global binary policy (points to 'local' primary and secondary policies */ -struct acm_binary_policy acm_bin_pol; -/* acm binary policy lock */ -DEFINE_RWLOCK(acm_bin_pol_rwlock); - -/* ACM's only accepted policy name during boot */ -char polname[80]; -char *acm_accepted_boot_policy_name = NULL; - -/* a lits of all chained ssid structures */ -LIST_HEAD(ssid_list); -DEFINE_RWLOCK(ssid_list_rwlock); - -static void __init set_dom0_ssidref(const char *val) -{ - /* expected format: - ssidref=<hex number>:<policy name> - Policy name must not have a 'space'. - */ - const char *c; - int lo, hi; - int i; - int dom0_ssidref = simple_strtoull(val, &c, 0); - - if (!strncmp(&c[0],":ACM:", 5)) { - lo = dom0_ssidref & 0xffff; - if (lo < ACM_MAX_NUM_TYPES && lo >= 1) - dom0_chwall_ssidref = lo; - hi = dom0_ssidref >> 16; - if (hi < ACM_MAX_NUM_TYPES && hi >= 1) - dom0_ste_ssidref = hi; - for (i = 0; i < sizeof(polname); i++) { - polname[i] = c[5+i]; - if (polname[i] == '\0' || polname[i] == '\t' || - polname[i] == '\n' || polname[i] == ' ' || - polname[i] == ':') { - break; - } - } - polname[i] = 0; - acm_accepted_boot_policy_name = polname; - } -} - -custom_param("ssidref", set_dom0_ssidref); - -int -acm_set_policy_reference(u8 *buf, u32 buf_size) -{ - char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer)); - struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf; - - if (acm_accepted_boot_policy_name != NULL) { - if (strcmp(acm_accepted_boot_policy_name, name)) { - printk("Policy's name '%s' is not the expected one '%s'.\n", - name, acm_accepted_boot_policy_name); - return ACM_ERROR; - } - } - - acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len)); - - if (!acm_bin_pol.policy_reference_name) - return -ENOMEM; - strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len)); - - printk("%s: Activating policy %s\n", __func__, - acm_bin_pol.policy_reference_name); - return 0; -} - -int -acm_dump_policy_reference(u8 *buf, u32 buf_size) -{ - struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf; - int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1; - - ret = (ret + 7) & ~7; - if (buf_size < ret) - return -EINVAL; - - memset(buf, 0, ret); - pr_buf->len = cpu_to_be32(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */ - strlcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)), - acm_bin_pol.policy_reference_name, - be32_to_cpu(pr_buf->len)); - return ret; -} - -int -acm_init_binary_policy(u32 policy_code) -{ - int ret = ACM_OK; - - acm_bin_pol.primary_policy_code = (policy_code & 0x0f); - acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f; - - write_lock(&acm_bin_pol_rwlock); - - /* set primary policy component */ - switch ((policy_code) & 0x0f) - { - - case ACM_CHINESE_WALL_POLICY: - acm_init_chwall_policy(); - acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; - acm_primary_ops = &acm_chinesewall_ops; - break; - - case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: - acm_init_ste_policy(); - acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; - acm_primary_ops = &acm_simple_type_enforcement_ops; - break; - - case ACM_NULL_POLICY: - acm_bin_pol.primary_policy_code = ACM_NULL_POLICY; - acm_primary_ops = &acm_null_ops; - break; - - default: - /* Unknown policy not allowed primary */ - ret = -EINVAL; - goto out; - } - - /* secondary policy component part */ - switch ((policy_code) >> 4) - { - - case ACM_NULL_POLICY: - acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; - acm_secondary_ops = &acm_null_ops; - break; - - case ACM_CHINESE_WALL_POLICY: - if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY) - { /* not a valid combination */ - ret = -EINVAL; - goto out; - } - acm_init_chwall_policy(); - acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY; - acm_secondary_ops = &acm_chinesewall_ops; - break; - - case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: - if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) - { /* not a valid combination */ - ret = -EINVAL; - goto out; - } - acm_init_ste_policy(); - acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; - acm_secondary_ops = &acm_simple_type_enforcement_ops; - break; - - default: - ret = -EINVAL; - goto out; - } - - out: - write_unlock(&acm_bin_pol_rwlock); - return ret; -} - -int -acm_is_policy(char *buf, unsigned long len) -{ - struct acm_policy_buffer *pol; - - if (buf == NULL || len < sizeof(struct acm_policy_buffer)) - return 0; - - pol = (struct acm_policy_buffer *)buf; - return be32_to_cpu(pol->magic) == ACM_MAGIC; -} - - -static int -acm_setup(char *policy_start, - unsigned long policy_len, - int is_bootpolicy) -{ - int rc = ACM_OK; - struct acm_policy_buffer *pol; - - if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer)) - return rc; - - pol = (struct acm_policy_buffer *)policy_start; - if (be32_to_cpu(pol->magic) != ACM_MAGIC) - return rc; - - rc = do_acm_set_policy((void *)policy_start, (u32)policy_len, - is_bootpolicy, - NULL, NULL, NULL); - if (rc == ACM_OK) - { - printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start); - } - else - { - printk("Invalid policy.\n"); - /* load default policy later */ - acm_active_security_policy = ACM_POLICY_UNDEFINED; - } - return rc; -} - - -int __init -acm_init(char *policy_start, - unsigned long policy_len) -{ - int ret = ACM_OK; - - /* first try to load the boot policy (uses its own locks) */ - acm_setup(policy_start, policy_len, 1); - - /* a user-provided policy may have any name; only matched during boot */ - acm_accepted_boot_policy_name = NULL; - - if (acm_active_security_policy != ACM_POLICY_UNDEFINED) - { - printk("%s: Enforcing %s boot policy.\n", __func__, - ACM_POLICY_NAME(acm_active_security_policy)); - goto out; - } - /* else continue with the minimal hardcoded default startup policy */ - printk("%s: Loading default policy (%s).\n", - __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY)); - - /* (re-)set dom-0 ssidref to default */ - dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001; - - if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) { - ret = -EINVAL; - goto out; - } - acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY; - if (acm_active_security_policy != ACM_NULL_POLICY) - acm_bin_pol.policy_reference_name = "DEFAULT"; - else - acm_bin_pol.policy_reference_name = "NULL"; - - out: - if (ret != ACM_OK) - { - printk("%s: Error initializing policies.\n", __func__); - /* here one could imagine a clean panic */ - return -EINVAL; - } - return ret; -} - -int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref) -{ - struct acm_ssid_domain *ssid; - int ret1, ret2; - if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL) - { - return ACM_INIT_SSID_ERROR; - } - - INIT_LIST_HEAD(&ssid->node); - ssid->datatype = ACM_DATATYPE_domain; - ssid->subject = subj; - ssid->domainid = subj->domain_id; - ssid->primary_ssid = NULL; - ssid->secondary_ssid = NULL; - - if (acm_active_security_policy != ACM_NULL_POLICY) - ssid->ssidref = ssidref; - else - ssid->ssidref = ACM_DEFAULT_SSID; - - subj->ssid = ssid; - /* now fill in primary and secondary parts; we only get here through hooks */ - if (acm_primary_ops->init_domain_ssid != NULL) - ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref); - else - ret1 = ACM_OK; - - if (acm_secondary_ops->init_domain_ssid != NULL) - ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref); - else - ret2 = ACM_OK; - - if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) - { - printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n", - __func__, subj->domain_id); - acm_free_domain_ssid(ssid); - return ACM_INIT_SSID_ERROR; - } - - printkd("%s: assigned domain %x the ssidref=%x.\n", - __func__, subj->domain_id, ssid->ssidref); - return ACM_OK; -} - - -void -acm_free_domain_ssid(struct acm_ssid_domain *ssid) -{ - /* domain is already gone, just ssid is left */ - if (ssid == NULL) - return; - - ssid->subject = NULL; - if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */ - acm_primary_ops->free_domain_ssid(ssid->primary_ssid); - ssid->primary_ssid = NULL; - if (acm_secondary_ops->free_domain_ssid != NULL) - acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid); - ssid->secondary_ssid = NULL; - - xfree(ssid); - printkd("%s: Freed individual domain ssid (domain=%02x).\n", - __func__, id); -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 12be90e2f831 -r 4ffca478e2f7 xen/acm/acm_null_hooks.c --- a/xen/acm/acm_null_hooks.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/**************************************************************** - * acm_null_hooks.c - * - * Copyright (C) 2005 IBM Corporation - * - * Author: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * - * 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, version 2 of the - * License. - */ - -#include <acm/acm_hooks.h> - -static int -null_init_domain_ssid(void **ssid, ssidref_t ssidref) -{ - return ACM_OK; -} - -static void -null_free_domain_ssid(void *ssid) -{ - return; -} - -static int -null_dump_binary_policy(u8 *buf, u32 buf_size) -{ - return 0; -} - -static int -null_test_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy, - struct acm_sized_buffer *errors) -{ - return ACM_OK; -} - -static int -null_set_binary_policy(u8 *buf, u32 buf_size) -{ - return ACM_OK; -} - -static int -null_dump_stats(u8 *buf, u16 buf_size) -{ - /* no stats for NULL policy */ - return 0; -} - -static int -null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size) -{ - /* no types */ - return 0; -} - - -/* now define the hook structure similarly to LSM */ -struct acm_operations acm_null_ops = { - .init_domain_ssid = null_init_domain_ssid, - .free_domain_ssid = null_free_domain_ssid, - .dump_binary_policy = null_dump_binary_policy, - .test_binary_policy = null_test_binary_policy, - .set_binary_policy = null_set_binary_policy, - .dump_statistics = null_dump_stats, - .dump_ssid_types = null_dump_ssid_types, - /* domain management control hooks */ - .domain_create = NULL, - .domain_destroy = NULL, - /* event channel control hooks */ - .pre_eventchannel_unbound = NULL, - .fail_eventchannel_unbound = NULL, - .pre_eventchannel_interdomain = NULL, - .fail_eventchannel_interdomain = NULL, - /* grant table control hooks */ - .pre_grant_map_ref = NULL, - .fail_grant_map_ref = NULL, - .pre_grant_setup = NULL, - .fail_grant_setup = NULL -}; - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 12be90e2f831 -r 4ffca478e2f7 xen/acm/acm_policy.c --- a/xen/acm/acm_policy.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,876 +0,0 @@ -/**************************************************************** - * acm_policy.c - * - * Copyright (C) 2005-2007 IBM Corporation - * - * Author: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * - * Contributors: - * Stefan Berger <stefanb@xxxxxxxxxxxxxx> - * - * 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, version 2 of the - * License. - * - * sHype access control policy management for Xen. - * This interface allows policy tools in authorized - * domains to interact with the Xen access control module - * - */ - -#include <xen/config.h> -#include <xen/errno.h> -#include <xen/types.h> -#include <xen/lib.h> -#include <xen/delay.h> -#include <xen/sched.h> -#include <xen/guest_access.h> -#include <public/xen.h> -#include <acm/acm_core.h> -#include <public/acm_ops.h> -#include <acm/acm_hooks.h> -#include <acm/acm_endian.h> -#include <asm/current.h> - -static int acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels, - struct acm_sized_buffer *errors); -static void acm_doms_change_ssidref(ssidref_t (*translator) - (const struct acm_ssid_domain *, - const struct acm_sized_buffer *), - struct acm_sized_buffer *translation_map); -static void acm_doms_restore_ssidref(void); -static ssidref_t oldssid_to_newssid(const struct acm_ssid_domain *, - const struct acm_sized_buffer *map); - - -int -acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size) -{ - u8 *policy_buffer = NULL; - int ret = -EFAULT; - - if ( buf_size < sizeof(struct acm_policy_buffer) ) - return -EFAULT; - - /* copy buffer from guest domain */ - if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL ) - return -ENOMEM; - - if ( copy_from_guest(policy_buffer, buf, buf_size) ) - { - printk("%s: Error copying!\n",__func__); - goto error_free; - } - ret = do_acm_set_policy(policy_buffer, buf_size, 0, - NULL, NULL, NULL); - - error_free: - xfree(policy_buffer); - return ret; -} - - -/* - * Update the policy of the running system by: - * - deleting ssidrefs that are not in the new policy anymore - * -> no running domain may use such an ssidref - * - assign new ssidrefs to domains based on their old ssidrefs - * - */ -static int -_acm_update_policy(void *buf, u32 buf_size, int is_bootpolicy, - struct acm_policy_buffer *pol, - struct acm_sized_buffer *deletions, - struct acm_sized_buffer *ssidchanges, - struct acm_sized_buffer *errors) -{ - uint32_t offset, length; - static int require_update = 0; - - write_lock(&acm_bin_pol_rwlock); - - if ( require_update != 0 && - ( deletions == NULL || ssidchanges == NULL ) ) - goto error_lock_free; - - require_update = 1; - /* - first some tests to check compatibility of new policy with - current state of system/domains - */ - - /* if ssidrefs are to be deleted, make sure no domain is using them */ - if ( deletions != NULL ) - if ( acm_check_deleted_ssidrefs(deletions, errors) ) - goto error_lock_free; - - if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) ) - /* assign all running domains new ssidrefs as requested */ - acm_doms_change_ssidref(oldssid_to_newssid, ssidchanges); - - /* test primary policy data with the new ssidrefs */ - offset = be32_to_cpu(pol->primary_buffer_offset); - length = be32_to_cpu(pol->secondary_buffer_offset) - offset; - - if ( (offset + length) > buf_size || - acm_primary_ops->test_binary_policy(buf + offset, length, - is_bootpolicy, - errors)) - goto error_lock_free; - - /* test secondary policy data with the new ssidrefs */ - offset = be32_to_cpu(pol->secondary_buffer_offset); - length = be32_to_cpu(pol->len) - offset; - if ( (offset + length) > buf_size || - acm_secondary_ops->test_binary_policy(buf + offset, length, - is_bootpolicy, - errors)) - goto error_lock_free; - - /* end of testing --- now real updates */ - - offset = be32_to_cpu(pol->policy_reference_offset); - length = be32_to_cpu(pol->primary_buffer_offset) - offset; - - /* set label reference name */ - if ( (offset + length) > buf_size || - acm_set_policy_reference(buf + offset, length) ) - goto error_lock_free; - - /* set primary policy data */ - offset = be32_to_cpu(pol->primary_buffer_offset); - length = be32_to_cpu(pol->secondary_buffer_offset) - offset; - - if ( acm_primary_ops->set_binary_policy(buf + offset, length) ) - goto error_lock_free; - - /* set secondary policy data */ - offset = be32_to_cpu(pol->secondary_buffer_offset); - length = be32_to_cpu(pol->len) - offset; - if ( acm_secondary_ops->set_binary_policy(buf + offset, length) ) - goto error_lock_free; - - memcpy(&acm_bin_pol.xml_pol_version, - &pol->xml_pol_version, - sizeof(acm_bin_pol.xml_pol_version)); - - if ( acm_primary_ops->is_default_policy() && - acm_secondary_ops->is_default_policy() ) - require_update = 0; - - write_unlock(&acm_bin_pol_rwlock); - - return ACM_OK; - -error_lock_free: - if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) ) - { - acm_doms_restore_ssidref(); - } - do_chwall_init_state_curr(NULL); - write_unlock(&acm_bin_pol_rwlock); - - return -EFAULT; -} - - -int -do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy, - struct acm_sized_buffer *deletions, - struct acm_sized_buffer *ssidchanges, - struct acm_sized_buffer *errors) -{ - struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf; - - /* some sanity checking */ - if ( (be32_to_cpu(pol->magic) != ACM_MAGIC) || - (buf_size != be32_to_cpu(pol->len)) || - (be32_to_cpu(pol->policy_version) != ACM_POLICY_VERSION) ) - { - printk("%s: ERROR in Magic, Version, or buf size.\n", __func__); - goto error_free; - } - - if ( acm_active_security_policy == ACM_POLICY_UNDEFINED ) - { - /* setup the policy with the boot policy */ - if ( acm_init_binary_policy( - (be32_to_cpu(pol->secondary_policy_code) << 4) | - be32_to_cpu(pol->primary_policy_code)) ) - { - goto error_free; - } - acm_active_security_policy = (acm_bin_pol.secondary_policy_code << 4) | - acm_bin_pol.primary_policy_code; - } - - /* once acm_active_security_policy is set, it cannot be changed */ - if ( (be32_to_cpu(pol->primary_policy_code) != - acm_bin_pol.primary_policy_code) || - (be32_to_cpu(pol->secondary_policy_code) != - acm_bin_pol.secondary_policy_code) ) - { - printkd("%s: Wrong policy type in boot policy!\n", __func__); - goto error_free; - } - - return _acm_update_policy(buf, buf_size, is_bootpolicy, - pol, - deletions, ssidchanges, - errors); - - error_free: - printk("%s: Error setting policy.\n", __func__); - return -EFAULT; -} - -int -acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size) -{ - u8 *policy_buffer; - int ret; - struct acm_policy_buffer *bin_pol; - - if ( buf_size < sizeof(struct acm_policy_buffer) ) - return -EFAULT; - - if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL ) - return -ENOMEM; - - read_lock(&acm_bin_pol_rwlock); - - bin_pol = (struct acm_policy_buffer *)policy_buffer; - bin_pol->magic = cpu_to_be32(ACM_MAGIC); - bin_pol->primary_policy_code = - cpu_to_be32(acm_bin_pol.primary_policy_code); - bin_pol->secondary_policy_code = - cpu_to_be32(acm_bin_pol.secondary_policy_code); - - bin_pol->len = cpu_to_be32(sizeof(struct acm_policy_buffer)); - bin_pol->policy_reference_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); - bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); - bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); - - memcpy(&bin_pol->xml_pol_version, - &acm_bin_pol.xml_pol_version, - sizeof(struct acm_policy_version)); - - ret = acm_dump_policy_reference( - policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset), - buf_size - be32_to_cpu(bin_pol->policy_reference_offset)); - - if ( ret < 0 ) - goto error_free_unlock; - - bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret); - bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); - - ret = acm_primary_ops->dump_binary_policy( - policy_buffer + be32_to_cpu(bin_pol->primary_buffer_offset), - buf_size - be32_to_cpu(bin_pol->primary_buffer_offset)); - - if ( ret < 0 ) - goto error_free_unlock; - - bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret); - bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len)); - - ret = acm_secondary_ops->dump_binary_policy( - policy_buffer + be32_to_cpu(bin_pol->secondary_buffer_offset), - buf_size - be32_to_cpu(bin_pol->secondary_buffer_offset)); - - if ( ret < 0 ) - goto error_free_unlock; - - bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret); - if ( copy_to_guest(buf, policy_buffer, be32_to_cpu(bin_pol->len)) ) - goto error_free_unlock; - - read_unlock(&acm_bin_pol_rwlock); - xfree(policy_buffer); - - return ACM_OK; - - error_free_unlock: - read_unlock(&acm_bin_pol_rwlock); - printk("%s: Error getting policy.\n", __func__); - xfree(policy_buffer); - - return -EFAULT; -} - -int -acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size) -{ - /* send stats to user space */ - u8 *stats_buffer; - int len1, len2; - struct acm_stats_buffer acm_stats; - - if ( (stats_buffer = xmalloc_array(u8, buf_size)) == NULL ) - return -ENOMEM; - - read_lock(&acm_bin_pol_rwlock); - - len1 = acm_primary_ops->dump_statistics( - stats_buffer + sizeof(struct acm_stats_buffer), - buf_size - sizeof(struct acm_stats_buffer)); - if ( len1 < 0 ) - goto error_lock_free; - - len2 = acm_secondary_ops->dump_statistics( - stats_buffer + sizeof(struct acm_stats_buffer) + len1, - buf_size - sizeof(struct acm_stats_buffer) - len1); - if ( len2 < 0 ) - goto error_lock_free; - - acm_stats.magic = cpu_to_be32(ACM_MAGIC); - acm_stats.primary_policy_code = - cpu_to_be32(acm_bin_pol.primary_policy_code); - acm_stats.secondary_policy_code = - cpu_to_be32(acm_bin_pol.secondary_policy_code); - acm_stats.primary_stats_offset = - cpu_to_be32(sizeof(struct acm_stats_buffer)); - acm_stats.secondary_stats_offset = - cpu_to_be32(sizeof(struct acm_stats_buffer) + len1); - acm_stats.len = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1 + len2); - - memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer)); - - if ( copy_to_guest(buf, - stats_buffer, - sizeof(struct acm_stats_buffer) + len1 + len2) ) - goto error_lock_free; - - read_unlock(&acm_bin_pol_rwlock); - xfree(stats_buffer); - - return ACM_OK; - - error_lock_free: - read_unlock(&acm_bin_pol_rwlock); - xfree(stats_buffer); - - return -EFAULT; -} - - -int -acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size) -{ - /* send stats to user space */ - u8 *ssid_buffer; - int ret; - struct acm_ssid_buffer *acm_ssid; - if ( buf_size < sizeof(struct acm_ssid_buffer) ) - return -EFAULT; - - if ( (ssid_buffer = xmalloc_array(u8, buf_size)) == NULL ) - return -ENOMEM; - - read_lock(&acm_bin_pol_rwlock); - - acm_ssid = (struct acm_ssid_buffer *)ssid_buffer; - acm_ssid->len = sizeof(struct acm_ssid_buffer); - acm_ssid->ssidref = ssidref; - acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code; - acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code; - - acm_ssid->policy_reference_offset = acm_ssid->len; - ret = acm_dump_policy_reference( - ssid_buffer + acm_ssid->policy_reference_offset, - buf_size - acm_ssid->policy_reference_offset); - if ( ret < 0 ) - goto error_free_unlock; - - acm_ssid->len += ret; - acm_ssid->primary_types_offset = acm_ssid->len; - - /* ret >= 0 --> ret == max_types */ - ret = acm_primary_ops->dump_ssid_types( - ACM_PRIMARY(ssidref), - ssid_buffer + acm_ssid->primary_types_offset, - buf_size - acm_ssid->primary_types_offset); - if ( ret < 0 ) - goto error_free_unlock; - - acm_ssid->len += ret; - acm_ssid->primary_max_types = ret; - acm_ssid->secondary_types_offset = acm_ssid->len; - - ret = acm_secondary_ops->dump_ssid_types( - ACM_SECONDARY(ssidref), - ssid_buffer + acm_ssid->secondary_types_offset, - buf_size - acm_ssid->secondary_types_offset); - if ( ret < 0 ) - goto error_free_unlock; - - acm_ssid->len += ret; - acm_ssid->secondary_max_types = ret; - - if ( copy_to_guest(buf, ssid_buffer, acm_ssid->len) ) - goto error_free_unlock; - - read_unlock(&acm_bin_pol_rwlock); - xfree(ssid_buffer); - - return ACM_OK; - - error_free_unlock: - read_unlock(&acm_bin_pol_rwlock); - printk("%s: Error getting ssid.\n", __func__); - xfree(ssid_buffer); - - return -ENOMEM; -} - -int -acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook) -{ - int ret = ACM_ACCESS_DENIED; - switch ( hook ) - { - - case ACMHOOK_sharing: - /* Sharing hook restricts access in STE policy only */ - ret = acm_sharing(ssidref1, ssidref2); - break; - - case ACMHOOK_authorization: - ret = acm_authorization(ssidref1, ssidref2); - break; - - default: - /* deny */ - break; - } - - printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n", - __func__, ssidref1, ssidref2, - (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED"); - - return ret; -} - - - -/* - Check if an ssidref of the current policy type is being used by any - domain. - */ -static int -acm_check_used_ssidref(uint32_t policy_type, uint32_t search_ssidref, - struct acm_sized_buffer *errors) -{ - int rc = 0; - struct acm_ssid_domain *rawssid; - - read_lock(&ssid_list_rwlock); - - for_each_acmssid( rawssid ) - { - ssidref_t ssidref; - void *s = GET_SSIDP(policy_type, rawssid); - - if ( policy_type == ACM_CHINESE_WALL_POLICY ) - { - ssidref = ((struct chwall_ssid *)s)->chwall_ssidref; - } else { - ssidref = ((struct ste_ssid *)s)->ste_ssidref; - } - gdprintk(XENLOG_INFO,"domid=%d: search ssidref=%d, ssidref=%d\n", - rawssid->domainid,search_ssidref,ssidref); - if ( ssidref == search_ssidref ) - { - /* one is enough */ - acm_array_append_tuple(errors, ACM_SSIDREF_IN_USE, search_ssidref); - rc = 1; - break; - } - } - - read_unlock(&ssid_list_rwlock); - - return rc; -} - - -/* - * Translate a current ssidref into its future representation under - * the new policy. - * The map provides translation of ssidrefs from old to new in tuples - * of (old ssidref, new ssidref). - */ -static ssidref_t -oldssid_to_newssid(const struct acm_ssid_domain *rawssid, - const struct acm_sized_buffer *map) -{ - uint i; - - if ( rawssid != NULL ) - { - ssidref_t ssid = rawssid->ssidref & 0xffff; - for ( i = 0; i + 1 < map->num_items; i += 2 ) - { - if ( map->array[i] == ssid ) - { - return (map->array[i+1] << 16 | map->array[i+1]); - } - } - } - return ACM_INVALID_SSIDREF; -} - - -/* - * Assign an ssidref to the CHWALL policy component of the domain - */ -static void -acm_pri_policy_assign_ssidref(struct acm_ssid_domain *rawssid, - ssidref_t new_ssid) -{ - struct chwall_ssid *chwall = (struct chwall_ssid *)rawssid->primary_ssid; - chwall->chwall_ssidref = new_ssid; -} - - -/* - * Assign an ssidref to the STE policy component of the domain - */ -static void -acm_sec_policy_assign_ssidref(struct acm_ssid_domain *rawssid, - ssidref_t new_ssid) -{ - struct ste_ssid *ste = (struct ste_ssid *)rawssid->secondary_ssid; - ste->ste_ssidref = new_ssid; -} - -/* - Change the ssidrefs on each domain using a passed translation function; - */ -static void -acm_doms_change_ssidref(ssidref_t (*translator_fn) - (const struct acm_ssid_domain *, - const struct acm_sized_buffer *), - struct acm_sized_buffer *translation_map) -{ - struct acm_ssid_domain *rawssid; - - write_lock(&ssid_list_rwlock); - - for_each_acmssid( rawssid ) - { - ssidref_t new_ssid; - - rawssid->old_ssidref = rawssid->ssidref; - - new_ssid = translator_fn(rawssid, translation_map); - if ( new_ssid == ACM_INVALID_SSIDREF ) - { - /* means no mapping found, so no change -- old = new */ - continue; - } - - acm_pri_policy_assign_ssidref(rawssid, ACM_PRIMARY (new_ssid) ); - acm_sec_policy_assign_ssidref(rawssid, ACM_SECONDARY(new_ssid) ); - - rawssid->ssidref = new_ssid; - } - - write_unlock(&ssid_list_rwlock); -} - -/* - * Restore the previous ssidref values on all domains - */ -static void -acm_doms_restore_ssidref(void) -{ - struct acm_ssid_domain *rawssid; - - write_lock(&ssid_list_rwlock); - - for_each_acmssid( rawssid ) - { - ssidref_t old_ssid; - - if ( rawssid->old_ssidref == rawssid->ssidref ) - continue; - - old_ssid = rawssid->old_ssidref & 0xffff; - rawssid->ssidref = rawssid->old_ssidref; - - acm_pri_policy_assign_ssidref(rawssid, old_ssid); - acm_sec_policy_assign_ssidref(rawssid, old_ssid); - } - - write_unlock(&ssid_list_rwlock); -} - - -/* - Check the list of domains whether either one of them uses a - to-be-deleted ssidref. - */ -static int -acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels, - struct acm_sized_buffer *errors) -{ - int rc = 0; - uint idx; - /* check for running domains that should not be there anymore */ - for ( idx = 0; idx < dels->num_items; idx++ ) - { - if ( acm_check_used_ssidref(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - dels->array[idx], - errors) > 0 || - acm_check_used_ssidref(ACM_CHINESE_WALL_POLICY, - dels->array[idx], - errors) > 0) - { - rc = ACM_ERROR; - break; - } - } - return rc; -} - - -/* - * Change the policy of the system. - */ -int -acm_change_policy(struct acm_change_policy *chgpolicy) -{ - int rc = 0; - u8 *binpolicy = NULL; - struct acm_sized_buffer dels = - { - .array = NULL, - }; - struct acm_sized_buffer ssidmap = - { - .array = NULL, - }; - struct acm_sized_buffer errors = - { - .array = NULL, - }; - - gdprintk(XENLOG_INFO, "change policy operation\n"); - - if ( (chgpolicy->delarray_size > 4096) || - (chgpolicy->chgarray_size > 4096) || - (chgpolicy->errarray_size > 4096)) - { - return ACM_ERROR; - } - - dels.num_items = chgpolicy->delarray_size / sizeof(uint32_t); - if ( dels.num_items > 0 ) - { - dels.array = xmalloc_array(uint32_t, dels.num_items); - if ( dels.array == NULL ) - { - rc = -ENOMEM; - goto acm_chg_policy_exit; - } - } - - ssidmap.num_items = chgpolicy->chgarray_size / sizeof(uint32_t); - if ( ssidmap.num_items > 0 ) - { - ssidmap.array = xmalloc_array(uint32_t, ssidmap.num_items); - if ( ssidmap.array == NULL ) - { - rc = -ENOMEM; - goto acm_chg_policy_exit; - } - } - - errors.num_items = chgpolicy->errarray_size / sizeof(uint32_t); - if ( errors.num_items > 0 ) - { - errors.array = xmalloc_array(uint32_t, errors.num_items); - if ( errors.array == NULL ) - { - rc = -ENOMEM; - goto acm_chg_policy_exit; - } - memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items); - } - - binpolicy = xmalloc_array(u8, - chgpolicy->policy_pushcache_size); - if ( binpolicy == NULL ) - { - rc = -ENOMEM; - goto acm_chg_policy_exit; - } - - if ( copy_from_guest(dels.array, - chgpolicy->del_array, - dels.num_items) || - copy_from_guest(ssidmap.array, - chgpolicy->chg_array, - ssidmap.num_items) || - copy_from_guest(binpolicy, - chgpolicy->policy_pushcache, - chgpolicy->policy_pushcache_size )) - { - rc = -EFAULT; - goto acm_chg_policy_exit; - } - - rc = do_acm_set_policy(binpolicy, - chgpolicy->policy_pushcache_size, - 0, - &dels, &ssidmap, &errors); - - if ( (errors.num_items > 0) && - copy_to_guest(chgpolicy->err_array, - errors.array, - errors.num_items ) ) - { - rc = -EFAULT; - goto acm_chg_policy_exit; - } - - -acm_chg_policy_exit: - xfree(dels.array); - xfree(ssidmap.array); - xfree(errors.array); - xfree(binpolicy); - - return rc; -} - - -/* - * Lookup the new ssidref given the domain's id. - * The translation map provides a list of tuples in the format - * (domid, new ssidref). - */ -static ssidref_t -domid_to_newssid(const struct acm_ssid_domain *rawssid, - const struct acm_sized_buffer *map) -{ - domid_t domid = rawssid->domainid; - uint i; - for ( i = 0; (i+1) < map->num_items; i += 2 ) - { - if ( map->array[i] == domid ) - return (ssidref_t)map->array[i+1]; - } - return ACM_INVALID_SSIDREF; -} - - -int -do_acm_relabel_doms(struct acm_sized_buffer *relabel_map, - struct acm_sized_buffer *errors) -{ - int rc = 0, irc; - - write_lock(&acm_bin_pol_rwlock); - - acm_doms_change_ssidref(domid_to_newssid, relabel_map); - - /* run tests; collect as much error info as possible */ - irc = do_chwall_init_state_curr(errors); - irc += do_ste_init_state_curr(errors); - if ( irc != 0 ) - { - rc = -EFAULT; - goto acm_relabel_doms_lock_err_exit; - } - - write_unlock(&acm_bin_pol_rwlock); - - return rc; - -acm_relabel_doms_lock_err_exit: - /* revert the new ssidref assignment */ - acm_doms_restore_ssidref(); - do_chwall_init_state_curr(NULL); - - write_unlock(&acm_bin_pol_rwlock); - - return rc; -} - - -int -acm_relabel_domains(struct acm_relabel_doms *relabel) -{ - int rc = ACM_OK; - struct acm_sized_buffer relabels = - { - .array = NULL, - }; - struct acm_sized_buffer errors = - { - .array = NULL, - }; - - if ( relabel->relabel_map_size > 4096 ) - { - return ACM_ERROR; - } - - relabels.num_items = relabel->relabel_map_size / sizeof(uint32_t); - if ( relabels.num_items > 0 ) - { - relabels.array = xmalloc_array(uint32_t, relabels.num_items); - if ( relabels.array == NULL ) - { - rc = -ENOMEM; - goto acm_relabel_doms_exit; - } - } - - errors.num_items = relabel->errarray_size / sizeof(uint32_t); - if ( errors.num_items > 0 ) - { - errors.array = xmalloc_array(uint32_t, errors.num_items); - if ( errors.array == NULL ) - { - rc = -ENOMEM; - goto acm_relabel_doms_exit; - } - memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items); - } - - if ( copy_from_guest(relabels.array, - relabel->relabel_map, - relabels.num_items) ) - { - rc = -EFAULT; - goto acm_relabel_doms_exit; - } - - rc = do_acm_relabel_doms(&relabels, &errors); - - if ( copy_to_guest(relabel->err_array, - errors.array, - errors.num_items ) ) - rc = -EFAULT; - -acm_relabel_doms_exit: - xfree(relabels.array); - xfree(errors.array); - return rc; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 12be90e2f831 -r 4ffca478e2f7 xen/acm/acm_simple_type_enforcement_hooks.c --- a/xen/acm/acm_simple_type_enforcement_hooks.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,914 +0,0 @@ -/**************************************************************** - * acm_simple_type_enforcement_hooks.c - * - * Copyright (C) 2005 IBM Corporation - * - * Author: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * - * Contributors: - * Stefan Berger <stefanb@xxxxxxxxxxxxxx> - * support for network order binary policies - * - * 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, version 2 of the - * License. - * - * sHype Simple Type Enforcement for Xen - * STE allows to control which domains can setup sharing - * (eventchannels right now) with which other domains. Hooks - * are defined and called throughout Xen when domains bind to - * shared resources (setup eventchannels) and a domain is allowed - * to setup sharing with another domain if and only if both domains - * share at least on common type. - * - */ - -#include <xen/lib.h> -#include <asm/types.h> -#include <asm/current.h> -#include <acm/acm_hooks.h> -#include <asm/atomic.h> -#include <acm/acm_endian.h> -#include <acm/acm_core.h> - -ssidref_t dom0_ste_ssidref = 0x0001; - -/* local cache structures for STE policy */ -struct ste_binary_policy ste_bin_pol; - -static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) -{ - int i; - - if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs && - ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs ) - { - for( i = 0; i< ste_bin_pol.max_types; i++ ) - if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] && - ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i]) - { - printkd("%s: common type #%02x.\n", __func__, i); - return 1; - } - } - return 0; -} - -static inline int is_superset(ssidref_t ref1, ssidref_t ref2) -{ - int i; - - if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs && - ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs ) - { - for( i = 0; i< ste_bin_pol.max_types; i++ ) - if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] && - ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i]) - { - return 0; - } - } else { - return 0; - } - return 1; -} - - -/* Helper function: return = (subj and obj share a common type) */ -static int share_common_type(struct domain *subj, struct domain *obj) -{ - ssidref_t ref_s, ref_o; - int ret; - - if ( (subj == NULL) || (obj == NULL) || - (subj->ssid == NULL) || (obj->ssid == NULL) ) - return 0; - - read_lock(&acm_bin_pol_rwlock); - - /* lookup the policy-local ssids */ - ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref; - ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref; - /* check whether subj and obj share a common ste type */ - ret = have_common_type(ref_s, ref_o); - - read_unlock(&acm_bin_pol_rwlock); - - return ret; -} - -/* - * Initializing STE policy (will be filled by policy partition - * using setpolicy command) - */ -int acm_init_ste_policy(void) -{ - /* minimal startup policy; policy write-locked already */ - ste_bin_pol.max_types = 1; - ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref; - ste_bin_pol.ssidrefs = - (domaintype_t *)xmalloc_array(domaintype_t, - ste_bin_pol.max_types * - ste_bin_pol.max_ssidrefs); - - if (ste_bin_pol.ssidrefs == NULL) - return ACM_INIT_SSID_ERROR; - - memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) * - ste_bin_pol.max_types * - ste_bin_pol.max_ssidrefs); - - /* initialize state so that dom0 can start up and communicate with itself */ - ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1; - - /* init stats */ - atomic_set(&(ste_bin_pol.ec_eval_count), 0); - atomic_set(&(ste_bin_pol.ec_denied_count), 0); - atomic_set(&(ste_bin_pol.ec_cachehit_count), 0); - atomic_set(&(ste_bin_pol.gt_eval_count), 0); - atomic_set(&(ste_bin_pol.gt_denied_count), 0); - atomic_set(&(ste_bin_pol.gt_cachehit_count), 0); - - return ACM_OK; -} - - -/* ste initialization function hooks */ -static int -ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref) -{ - int i; - struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid); - - if ( ste_ssidp == NULL ) - return ACM_INIT_SSID_ERROR; - - /* get policy-local ssid reference */ - ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - ssidref); - - if ( (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) ) - { - printkd("%s: ERROR ste_ssidref (%x) undefined or unset (0).\n", - __func__, ste_ssidp->ste_ssidref); - xfree(ste_ssidp); - return ACM_INIT_SSID_ERROR; - } - /* clean ste cache */ - for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ ) - ste_ssidp->ste_cache[i].valid = ACM_STE_free; - - (*ste_ssid) = ste_ssidp; - printkd("%s: determined ste_ssidref to %x.\n", - __func__, ste_ssidp->ste_ssidref); - - return ACM_OK; -} - - -static void -ste_free_domain_ssid(void *ste_ssid) -{ - xfree(ste_ssid); - return; -} - -/* dump type enforcement cache; policy read-locked already */ -static int -ste_dump_policy(u8 *buf, u32 buf_size) { - struct acm_ste_policy_buffer *ste_buf = - (struct acm_ste_policy_buffer *)buf; - int ret = 0; - - if ( buf_size < sizeof(struct acm_ste_policy_buffer) ) - return -EINVAL; - - ste_buf->ste_max_types = cpu_to_be32(ste_bin_pol.max_types); - ste_buf->ste_max_ssidrefs = cpu_to_be32(ste_bin_pol.max_ssidrefs); - ste_buf->policy_code = cpu_to_be32(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - ste_buf->ste_ssid_offset = - cpu_to_be32(sizeof(struct acm_ste_policy_buffer)); - ret = be32_to_cpu(ste_buf->ste_ssid_offset) + - sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types; - - ret = (ret + 7) & ~7; - - if (buf_size < ret) - return -EINVAL; - - /* now copy buffer over */ - arrcpy(buf + be32_to_cpu(ste_buf->ste_ssid_offset), - ste_bin_pol.ssidrefs, - sizeof(domaintype_t), - ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types); - - return ret; -} - -/* - * ste_init_state is called when a policy is changed to detect violations - * (return != 0). from a security point of view, we simulate that all - * running domains are re-started and all sharing decisions are replayed - * to detect violations or current sharing behavior (right now: - * event_channels, future: also grant_tables) - */ -static int -ste_init_state(struct acm_sized_buffer *errors) -{ - int violation = 1; - struct ste_ssid *ste_ssid, *ste_rssid; - ssidref_t ste_ssidref, ste_rssidref; - struct domain *d, *rdom; - domid_t rdomid; - struct active_grant_entry *act; - int port, i; - - rcu_read_lock(&domlist_read_lock); - read_lock(&ssid_list_rwlock); - - /* go through all domains and adjust policy as if this domain was - started now */ - - for_each_domain ( d ) - { - struct evtchn *ports; - unsigned int bucket; - - ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)d->ssid); - ste_ssidref = ste_ssid->ste_ssidref; - traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n", - __func__, d->domain_id, ste_ssidref); - /* a) check for event channel conflicts */ - for ( bucket = 0; bucket < NR_EVTCHN_BUCKETS; bucket++ ) - { - spin_lock(&d->evtchn_lock); - ports = d->evtchn[bucket]; - if ( ports == NULL) - { - spin_unlock(&d->evtchn_lock); - break; - } - - for ( port = 0; port < EVTCHNS_PER_BUCKET; port++ ) - { - if ( ports[port].state == ECS_INTERDOMAIN ) - { - rdom = ports[port].u.interdomain.remote_dom; - rdomid = rdom->domain_id; - } else { - continue; /* port unused */ - } - - /* rdom now has remote domain */ - ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)(rdom->ssid)); - ste_rssidref = ste_rssid->ste_ssidref; - traceprintk("%s: eventch: domain %x (ssidref %x) --> " - "domain %x (rssidref %x) used (port %x).\n", - __func__, d->domain_id, ste_ssidref, - rdom->domain_id, ste_rssidref, port); - /* check whether on subj->ssid, obj->ssid share a common type*/ - if ( ! have_common_type(ste_ssidref, ste_rssidref) ) - { - printkd("%s: Policy violation in event channel domain " - "%x -> domain %x.\n", - __func__, d->domain_id, rdomid); - spin_unlock(&d->evtchn_lock); - - acm_array_append_tuple(errors, - ACM_EVTCHN_SHARING_VIOLATION, - d->domain_id << 16 | rdomid); - goto out; - } - } - spin_unlock(&d->evtchn_lock); - } - - - /* b) check for grant table conflicts on shared pages */ - spin_lock(&d->grant_table->lock); - for ( i = 0; i < nr_active_grant_frames(d->grant_table); i++ ) - { -#define APP (PAGE_SIZE / sizeof(struct active_grant_entry)) - act = &d->grant_table->active[i/APP][i%APP]; - if ( act->pin != 0 ) { - printkd("%s: grant dom (%hu) SHARED (%d) pin (%d) " - "dom:(%hu) frame:(%lx)\n", - __func__, d->domain_id, i, act->pin, - act->domid, (unsigned long)act->frame); - rdomid = act->domid; - if ( (rdom = rcu_lock_domain_by_id(rdomid)) == NULL ) - { - spin_unlock(&d->grant_table->lock); - printkd("%s: domain not found ERROR!\n", __func__); - - acm_array_append_tuple(errors, - ACM_DOMAIN_LOOKUP, - rdomid); - goto out; - } - /* rdom now has remote domain */ - ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)(rdom->ssid)); - ste_rssidref = ste_rssid->ste_ssidref; - rcu_unlock_domain(rdom); - if ( ! have_common_type(ste_ssidref, ste_rssidref) ) - { - spin_unlock(&d->grant_table->lock); - printkd("%s: Policy violation in grant table " - "sharing domain %x -> domain %x.\n", - __func__, d->domain_id, rdomid); - - acm_array_append_tuple(errors, - ACM_GNTTAB_SHARING_VIOLATION, - d->domain_id << 16 | rdomid); - goto out; - } - } - } - spin_unlock(&d->grant_table->lock); - } - violation = 0; - out: - read_unlock(&ssid_list_rwlock); - rcu_read_unlock(&domlist_read_lock); - return violation; - /* - returning "violation != 0" means that existing sharing between domains - would not have been allowed if the new policy had been enforced before - the sharing; for ste, this means that there are at least 2 domains - that have established sharing through event-channels or grant-tables - but these two domains don't have no longer a common type in their - typesets referenced by their ssidrefs - */ -} - - -/* - * Call ste_init_state with the current policy. - */ -int -do_ste_init_state_curr(struct acm_sized_buffer *errors) -{ - return ste_init_state(errors); -} - - -/* set new policy; policy write-locked already */ -static int -_ste_update_policy(u8 *buf, u32 buf_size, int test_only, - struct acm_sized_buffer *errors) -{ - int rc = -EFAULT; - struct acm_ste_policy_buffer *ste_buf = - (struct acm_ste_policy_buffer *)buf; - void *ssidrefsbuf; - struct ste_ssid *ste_ssid; - struct acm_ssid_domain *rawssid; - int i; - - - /* 1. create and copy-in new ssidrefs buffer */ - ssidrefsbuf = xmalloc_array(u8, - sizeof(domaintype_t) * - ste_buf->ste_max_types * - ste_buf->ste_max_ssidrefs); - if ( ssidrefsbuf == NULL ) { - return -ENOMEM; - } - if ( ste_buf->ste_ssid_offset + - sizeof(domaintype_t) * - ste_buf->ste_max_ssidrefs * - ste_buf->ste_max_types > buf_size ) - goto error_free; - - arrcpy(ssidrefsbuf, - buf + ste_buf->ste_ssid_offset, - sizeof(domaintype_t), - ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types); - - - /* - * 3. in test mode: re-calculate sharing decisions based on running - * domains; this can fail if new policy is conflicting with sharing - * of running domains - * now: reject violating new policy; future: adjust sharing through - * revoking sharing - */ - - if ( test_only ) { - /* temporarily replace old policy with new one for the testing */ - struct ste_binary_policy orig_ste_bin_pol = ste_bin_pol; - ste_bin_pol.max_types = ste_buf->ste_max_types; - ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs; - ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf; - - if ( ste_init_state(errors) ) - { - /* new policy conflicts with sharing of running domains */ - printk("%s: New policy conflicts with running domains. " - "Policy load aborted.\n", __func__); - } else { - rc = ACM_OK; - } - /* revert changes, no matter whether testing was successful or not */ - ste_bin_pol = orig_ste_bin_pol; - goto error_free; - } - - /* 3. replace old policy (activate new policy) */ - ste_bin_pol.max_types = ste_buf->ste_max_types; - ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs; - xfree(ste_bin_pol.ssidrefs); - ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf; - - /* clear all ste caches */ - read_lock(&ssid_list_rwlock); - - for_each_acmssid( rawssid ) - { - ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid); - for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ ) - ste_ssid->ste_cache[i].valid = ACM_STE_free; - } - - read_unlock(&ssid_list_rwlock); - - return ACM_OK; - - error_free: - if ( !test_only ) - printk("%s: ERROR setting policy.\n", __func__); - xfree(ssidrefsbuf); - return rc; -} - -static int -ste_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy, - struct acm_sized_buffer *errors) -{ - struct acm_ste_policy_buffer *ste_buf = - (struct acm_ste_policy_buffer *)buf; - - if ( buf_size < sizeof(struct acm_ste_policy_buffer) ) - return -EINVAL; - - /* Convert endianess of policy */ - ste_buf->policy_code = be32_to_cpu(ste_buf->policy_code); - ste_buf->policy_version = be32_to_cpu(ste_buf->policy_version); - ste_buf->ste_max_types = be32_to_cpu(ste_buf->ste_max_types); - ste_buf->ste_max_ssidrefs = be32_to_cpu(ste_buf->ste_max_ssidrefs); - ste_buf->ste_ssid_offset = be32_to_cpu(ste_buf->ste_ssid_offset); - - /* policy type and version checks */ - if ( (ste_buf->policy_code != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) || - (ste_buf->policy_version != ACM_STE_VERSION) ) - return -EINVAL; - - /* during boot dom0_chwall_ssidref is set */ - if ( is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs) ) - return -EINVAL; - - return _ste_update_policy(buf, buf_size, 1, errors); -} - -static int -ste_set_policy(u8 *buf, u32 buf_size) -{ - return _ste_update_policy(buf, buf_size, 0, NULL); -} - -static int -ste_dump_stats(u8 *buf, u16 buf_len) -{ - struct acm_ste_stats_buffer stats; - - /* now send the hook counts to user space */ - stats.ec_eval_count = - cpu_to_be32(atomic_read(&ste_bin_pol.ec_eval_count)); - stats.gt_eval_count = - cpu_to_be32(atomic_read(&ste_bin_pol.gt_eval_count)); - stats.ec_denied_count = - cpu_to_be32(atomic_read(&ste_bin_pol.ec_denied_count)); - stats.gt_denied_count = - cpu_to_be32(atomic_read(&ste_bin_pol.gt_denied_count)); - stats.ec_cachehit_count = - cpu_to_be32(atomic_read(&ste_bin_pol.ec_cachehit_count)); - stats.gt_cachehit_count = - cpu_to_be32(atomic_read(&ste_bin_pol.gt_cachehit_count)); - - if ( buf_len < sizeof(struct acm_ste_stats_buffer) ) - return -ENOMEM; - - memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer)); - - return sizeof(struct acm_ste_stats_buffer); -} - -static int -ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len) -{ - int i; - - /* fill in buffer */ - if ( ste_bin_pol.max_types > len ) - return -EFAULT; - - if ( ssidref >= ste_bin_pol.max_ssidrefs ) - return -EFAULT; - - /* read types for chwall ssidref */ - for( i = 0; i< ste_bin_pol.max_types; i++ ) - { - if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i]) - buf[i] = 1; - else - buf[i] = 0; - } - return ste_bin_pol.max_types; -} - -/* we need to go through this before calling the hooks, - * returns 1 == cache hit */ -static int inline -check_cache(struct domain *dom, domid_t rdom) -{ - struct ste_ssid *ste_ssid; - int i; - - printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom); - - if (dom->ssid == NULL) - return 0; - ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)(dom->ssid)); - - for( i = 0; i < ACM_TE_CACHE_SIZE; i++ ) - { - if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) && - (ste_ssid->ste_cache[i].id == rdom) ) - { - printkd("cache hit (entry %x, id= %x!\n", - i, - ste_ssid->ste_cache[i].id); - return 1; - } - } - return 0; -} - - -/* we only get here if there is NO entry yet; no duplication check! */ -static void inline -cache_result(struct domain *subj, struct domain *obj) { - struct ste_ssid *ste_ssid; - int i; - - printkd("caching from doms: %x --> %x.\n", - subj->domain_id, obj->domain_id); - - if ( subj->ssid == NULL ) - return; - - ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - (struct acm_ssid_domain *)(subj)->ssid); - - for( i = 0; i < ACM_TE_CACHE_SIZE; i++ ) - if ( ste_ssid->ste_cache[i].valid == ACM_STE_free ) - break; - if ( i < ACM_TE_CACHE_SIZE ) - { - ste_ssid->ste_cache[i].valid = ACM_STE_valid; - ste_ssid->ste_cache[i].id = obj->domain_id; - } else - printk ("Cache of dom %x is full!\n", subj->domain_id); -} - -/* deletes entries for domain 'id' from all caches (re-use) */ -static void inline -clean_id_from_cache(domid_t id) -{ - struct ste_ssid *ste_ssid; - int i; - struct acm_ssid_domain *rawssid; - - printkd("deleting cache for dom %x.\n", id); - - read_lock(&ssid_list_rwlock); - /* look through caches of all domains */ - - for_each_acmssid ( rawssid ) - { - ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid); - - if ( !ste_ssid ) - { - printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n", - __func__); - goto out; - } - for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ ) - if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) && - (ste_ssid->ste_cache[i].id == id) ) - ste_ssid->ste_cache[i].valid = ACM_STE_free; - } - - out: - read_unlock(&ssid_list_rwlock); -} - -/*************************** - * Authorization functions - **************************/ -static int -ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref) -{ - /* check for ssidref in range for policy */ - ssidref_t ste_ssidref; - - traceprintk("%s.\n", __func__); - - read_lock(&acm_bin_pol_rwlock); - - ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref); - - if ( ste_ssidref >= ste_bin_pol.max_ssidrefs ) - { - printk("%s: ERROR ste_ssidref > max(%x).\n", - __func__, ste_bin_pol.max_ssidrefs-1); - read_unlock(&acm_bin_pol_rwlock); - return ACM_ACCESS_DENIED; - } - - read_unlock(&acm_bin_pol_rwlock); - - return ACM_ACCESS_PERMITTED; -} - -static int -ste_domain_create(void *subject_ssid, ssidref_t ssidref, domid_t domid) -{ - return ste_pre_domain_create(subject_ssid, ssidref); -} - - -static void -ste_domain_destroy(void *subject_ssid, struct domain *d) -{ - /* clean all cache entries for destroyed domain (might be re-used) */ - clean_id_from_cache(d->domain_id); -} - -/* -------- EVENTCHANNEL OPERATIONS -----------*/ -static int -ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) { - struct domain *subj, *obj; - int ret; - traceprintk("%s: dom%x-->dom%x.\n", __func__, - (id1 == DOMID_SELF) ? current->domain->domain_id : id1, - (id2 == DOMID_SELF) ? current->domain->domain_id : id2); - - if ( id1 == DOMID_SELF ) - id1 = current->domain->domain_id; - if ( id2 == DOMID_SELF ) - id2 = current->domain->domain_id; - - subj = rcu_lock_domain_by_id(id1); - obj = rcu_lock_domain_by_id(id2); - if ( (subj == NULL) || (obj == NULL) ) - { - ret = ACM_ACCESS_DENIED; - goto out; - } - /* cache check late */ - if ( check_cache(subj, obj->domain_id) ) - { - atomic_inc(&ste_bin_pol.ec_cachehit_count); - ret = ACM_ACCESS_PERMITTED; - goto out; - } - atomic_inc(&ste_bin_pol.ec_eval_count); - - if ( share_common_type(subj, obj) ) - { - cache_result(subj, obj); - ret = ACM_ACCESS_PERMITTED; - } - else - { - atomic_inc(&ste_bin_pol.ec_denied_count); - ret = ACM_ACCESS_DENIED; - } - - out: - if ( obj != NULL ) - rcu_unlock_domain(obj); - if ( subj != NULL ) - rcu_unlock_domain(subj); - return ret; -} - -static int -ste_pre_eventchannel_interdomain(domid_t id) -{ - struct domain *subj=NULL, *obj=NULL; - int ret; - - traceprintk("%s: dom%x-->dom%x.\n", __func__, - current->domain->domain_id, - (id == DOMID_SELF) ? current->domain->domain_id : id); - - /* following is a bit longer but ensures that we - * "put" only domains that we where "find"-ing - */ - if ( id == DOMID_SELF ) - id = current->domain->domain_id; - - subj = current->domain; - obj = rcu_lock_domain_by_id(id); - if ( obj == NULL ) - { - ret = ACM_ACCESS_DENIED; - goto out; - } - - /* cache check late, but evtchn is not on performance critical path */ - if ( check_cache(subj, obj->domain_id) ) - { - atomic_inc(&ste_bin_pol.ec_cachehit_count); - ret = ACM_ACCESS_PERMITTED; - goto out; - } - - atomic_inc(&ste_bin_pol.ec_eval_count); - - if ( share_common_type(subj, obj) ) - { - cache_result(subj, obj); - ret = ACM_ACCESS_PERMITTED; - } - else - { - atomic_inc(&ste_bin_pol.ec_denied_count); - ret = ACM_ACCESS_DENIED; - } - - out: - if ( obj != NULL ) - rcu_unlock_domain(obj); - return ret; -} - -/* -------- SHARED MEMORY OPERATIONS -----------*/ - -static int -ste_pre_grant_map_ref (domid_t id) -{ - struct domain *obj, *subj; - int ret; - traceprintk("%s: dom%x-->dom%x.\n", __func__, - current->domain->domain_id, id); - - if ( check_cache(current->domain, id) ) - { - atomic_inc(&ste_bin_pol.gt_cachehit_count); - return ACM_ACCESS_PERMITTED; - } - atomic_inc(&ste_bin_pol.gt_eval_count); - subj = current->domain; - obj = rcu_lock_domain_by_id(id); - - if ( share_common_type(subj, obj) ) - { - cache_result(subj, obj); - ret = ACM_ACCESS_PERMITTED; - } - else - { - atomic_inc(&ste_bin_pol.gt_denied_count); - printkd("%s: ACCESS DENIED!\n", __func__); - ret = ACM_ACCESS_DENIED; - } - if ( obj != NULL ) - rcu_unlock_domain(obj); - return ret; -} - - -/* since setting up grant tables involves some implicit information - flow from the creating domain to the domain that is setup, we - check types in addition to the general authorization */ -static int -ste_pre_grant_setup (domid_t id) -{ - struct domain *obj, *subj; - int ret; - traceprintk("%s: dom%x-->dom%x.\n", __func__, - current->domain->domain_id, id); - - if ( check_cache(current->domain, id) ) - { - atomic_inc(&ste_bin_pol.gt_cachehit_count); - return ACM_ACCESS_PERMITTED; - } - atomic_inc(&ste_bin_pol.gt_eval_count); - /* a) check authorization (eventually use specific capabilities) */ - if ( !IS_PRIV(current->domain) ) - { - printk("%s: Grant table management authorization denied ERROR!\n", - __func__); - return ACM_ACCESS_DENIED; - } - /* b) check types */ - subj = current->domain; - obj = rcu_lock_domain_by_id(id); - - if ( share_common_type(subj, obj) ) - { - cache_result(subj, obj); - ret = ACM_ACCESS_PERMITTED; - } - else - { - atomic_inc(&ste_bin_pol.gt_denied_count); - ret = ACM_ACCESS_DENIED; - } - if ( obj != NULL ) - rcu_unlock_domain(obj); - return ret; -} - -/* -------- DOMAIN-Requested Decision hooks -----------*/ - -static int -ste_sharing(ssidref_t ssidref1, ssidref_t ssidref2) -{ - int hct = have_common_type( - GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1), - GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2)); - return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED); -} - -static int -ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2) -{ - int iss = is_superset( - GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1), - GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2)); - return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED); -} - -static int -ste_is_default_policy(void) -{ - return ((ste_bin_pol.max_types == 1) && - (ste_bin_pol.max_ssidrefs == 2)); -} - -/* now define the hook structure similarly to LSM */ -struct acm_operations acm_simple_type_enforcement_ops = { - - /* policy management services */ - .init_domain_ssid = ste_init_domain_ssid, - .free_domain_ssid = ste_free_domain_ssid, - .dump_binary_policy = ste_dump_policy, - .test_binary_policy = ste_test_policy, - .set_binary_policy = ste_set_policy, - .dump_statistics = ste_dump_stats, - .dump_ssid_types = ste_dump_ssid_types, - - /* domain management control hooks */ - .domain_create = ste_domain_create, - .domain_destroy = ste_domain_destroy, - - /* event channel control hooks */ - .pre_eventchannel_unbound = ste_pre_eventchannel_unbound, - .fail_eventchannel_unbound = NULL, - .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain, - .fail_eventchannel_interdomain = NULL, - - /* grant table control hooks */ - .pre_grant_map_ref = ste_pre_grant_map_ref, - .fail_grant_map_ref = NULL, - .pre_grant_setup = ste_pre_grant_setup, - .fail_grant_setup = NULL, - .sharing = ste_sharing, - .authorization = ste_authorization, - - .is_default_policy = ste_is_default_policy, -}; - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/ia64/xen/domain.c Thu Sep 06 12:05:15 2007 -0600 @@ -563,6 +563,7 @@ int arch_domain_create(struct domain *d) goto fail_nomem; memset(&d->arch.mm, 0, sizeof(d->arch.mm)); + d->arch.mm_teardown_offset = 0; if ((d->arch.mm.pgd = pgd_alloc(&d->arch.mm)) == NULL) goto fail_nomem; @@ -936,14 +937,17 @@ static void relinquish_memory(struct dom spin_unlock_recursive(&d->page_alloc_lock); } -void domain_relinquish_resources(struct domain *d) -{ +int domain_relinquish_resources(struct domain *d) +{ + int ret; /* Relinquish guest resources for VT-i domain. */ if (d->arch.is_vti) vmx_relinquish_guest_resources(d); /* Tear down shadow mode stuff. */ - mm_teardown(d); + ret = mm_teardown(d); + if (ret != 0) + return ret; /* Relinquish every page of memory. */ relinquish_memory(d, &d->xenpage_list); @@ -954,6 +958,8 @@ void domain_relinquish_resources(struct /* Free page used by xen oprofile buffer */ free_xenoprof_pages(d); + + return 0; } unsigned long diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/ia64/xen/mm.c Thu Sep 06 12:05:15 2007 -0600 @@ -215,6 +215,18 @@ alloc_dom_xen_and_dom_io(void) BUG_ON(dom_io == NULL); } +static int +mm_teardown_can_skip(struct domain* d, unsigned long offset) +{ + return d->arch.mm_teardown_offset > offset; +} + +static void +mm_teardown_update_offset(struct domain* d, unsigned long offset) +{ + d->arch.mm_teardown_offset = offset; +} + static void mm_teardown_pte(struct domain* d, volatile pte_t* pte, unsigned long offset) { @@ -252,46 +264,73 @@ mm_teardown_pte(struct domain* d, volati } } -static void +static int mm_teardown_pmd(struct domain* d, volatile pmd_t* pmd, unsigned long offset) { unsigned long i; volatile pte_t* pte = pte_offset_map(pmd, offset); for (i = 0; i < PTRS_PER_PTE; i++, pte++) { - if (!pte_present(*pte)) // acquire semantics + unsigned long cur_offset = offset + (i << PAGE_SHIFT); + if (mm_teardown_can_skip(d, cur_offset + PAGE_SIZE)) continue; - mm_teardown_pte(d, pte, offset + (i << PAGE_SHIFT)); - } -} - -static void + if (!pte_present(*pte)) { // acquire semantics + mm_teardown_update_offset(d, cur_offset); + continue; + } + mm_teardown_update_offset(d, cur_offset); + mm_teardown_pte(d, pte, cur_offset); + if (hypercall_preempt_check()) + return -EAGAIN; + } + return 0; +} + +static int mm_teardown_pud(struct domain* d, volatile pud_t *pud, unsigned long offset) { unsigned long i; volatile pmd_t *pmd = pmd_offset(pud, offset); for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { - if (!pmd_present(*pmd)) // acquire semantics + unsigned long cur_offset = offset + (i << PMD_SHIFT); + if (mm_teardown_can_skip(d, cur_offset + PMD_SIZE)) continue; - mm_teardown_pmd(d, pmd, offset + (i << PMD_SHIFT)); - } -} - -static void + if (!pmd_present(*pmd)) { // acquire semantics + mm_teardown_update_offset(d, cur_offset); + continue; + } + if (mm_teardown_pmd(d, pmd, cur_offset)) + return -EAGAIN; + } + return 0; +} + +static int mm_teardown_pgd(struct domain* d, volatile pgd_t *pgd, unsigned long offset) { unsigned long i; volatile pud_t *pud = pud_offset(pgd, offset); for (i = 0; i < PTRS_PER_PUD; i++, pud++) { - if (!pud_present(*pud)) // acquire semantics + unsigned long cur_offset = offset + (i << PUD_SHIFT); +#ifndef __PAGETABLE_PUD_FOLDED + if (mm_teardown_can_skip(d, cur_offset + PUD_SIZE)) continue; - mm_teardown_pud(d, pud, offset + (i << PUD_SHIFT)); - } -} - -void +#endif + if (!pud_present(*pud)) { // acquire semantics +#ifndef __PAGETABLE_PUD_FOLDED + mm_teardown_update_offset(d, cur_offset); +#endif + continue; + } + if (mm_teardown_pud(d, pud, cur_offset)) + return -EAGAIN; + } + return 0; +} + +int mm_teardown(struct domain* d) { struct mm_struct* mm = &d->arch.mm; diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/ia64/xen/xensetup.c Thu Sep 06 12:05:15 2007 -0600 @@ -28,7 +28,7 @@ #include <asm/iosapic.h> #include <xen/softirq.h> #include <xen/rcupdate.h> -#include <acm/acm_hooks.h> +#include <xsm/acm/acm_hooks.h> #include <asm/sn/simulator.h> unsigned long xenheap_phys_end, total_pages; diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/powerpc/domain.c --- a/xen/arch/powerpc/domain.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/powerpc/domain.c Thu Sep 06 12:05:15 2007 -0600 @@ -313,13 +313,13 @@ static void relinquish_memory(struct dom spin_unlock_recursive(&d->page_alloc_lock); } -void domain_relinquish_resources(struct domain *d) +int domain_relinquish_resources(struct domain *d) { relinquish_memory(d, &d->xenpage_list); relinquish_memory(d, &d->page_list); xfree(d->arch.foreign_mfns); xfree(d->arch.p2m); - return; + return 0; } void arch_dump_domain_info(struct domain *d) diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/powerpc/setup.c --- a/xen/arch/powerpc/setup.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/powerpc/setup.c Thu Sep 06 12:05:15 2007 -0600 @@ -38,7 +38,7 @@ #include <xen/numa.h> #include <xen/rcupdate.h> #include <xen/version.h> -#include <acm/acm_hooks.h> +#include <xsm/acm/acm_hooks.h> #include <public/version.h> #include <asm/mpic.h> #include <asm/processor.h> diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/Makefile --- a/xen/arch/x86/cpu/Makefile Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/x86/cpu/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -8,5 +8,4 @@ obj-y += intel_cacheinfo.o obj-$(x86_32) += centaur.o obj-$(x86_32) += cyrix.o -obj-$(x86_32) += rise.o obj-$(x86_32) += transmeta.o diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/centaur.c --- a/xen/arch/x86/cpu/centaur.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/x86/cpu/centaur.c Thu Sep 06 12:05:15 2007 -0600 @@ -6,248 +6,6 @@ #include <asm/msr.h> #include <asm/e820.h> #include "cpu.h" - -#ifdef CONFIG_X86_OOSTORE - -static u32 __init power2(u32 x) -{ - u32 s=1; - while(s<=x) - s<<=1; - return s>>=1; -} - - -/* - * Set up an actual MCR - */ - -static void __init centaur_mcr_insert(int reg, u32 base, u32 size, int key) -{ - u32 lo, hi; - - hi = base & ~0xFFF; - lo = ~(size-1); /* Size is a power of 2 so this makes a mask */ - lo &= ~0xFFF; /* Remove the ctrl value bits */ - lo |= key; /* Attribute we wish to set */ - wrmsr(reg+MSR_IDT_MCR0, lo, hi); - mtrr_centaur_report_mcr(reg, lo, hi); /* Tell the mtrr driver */ -} - -/* - * Figure what we can cover with MCR's - * - * Shortcut: We know you can't put 4Gig of RAM on a winchip - */ - -static u32 __init ramtop(void) /* 16388 */ -{ - int i; - u32 top = 0; - u32 clip = 0xFFFFFFFFUL; - - for (i = 0; i < e820.nr_map; i++) { - unsigned long start, end; - - if (e820.map[i].addr > 0xFFFFFFFFUL) - continue; - /* - * Don't MCR over reserved space. Ignore the ISA hole - * we frob around that catastrophy already - */ - - if (e820.map[i].type == E820_RESERVED) - { - if(e820.map[i].addr >= 0x100000UL && e820.map[i].addr < clip) - clip = e820.map[i].addr; - continue; - } - start = e820.map[i].addr; - end = e820.map[i].addr + e820.map[i].size; - if (start >= end) - continue; - if (end > top) - top = end; - } - /* Everything below 'top' should be RAM except for the ISA hole. - Because of the limited MCR's we want to map NV/ACPI into our - MCR range for gunk in RAM - - Clip might cause us to MCR insufficient RAM but that is an - acceptable failure mode and should only bite obscure boxes with - a VESA hole at 15Mb - - The second case Clip sometimes kicks in is when the EBDA is marked - as reserved. Again we fail safe with reasonable results - */ - - if(top>clip) - top=clip; - - return top; -} - -/* - * Compute a set of MCR's to give maximum coverage - */ - -static int __init centaur_mcr_compute(int nr, int key) -{ - u32 mem = ramtop(); - u32 root = power2(mem); - u32 base = root; - u32 top = root; - u32 floor = 0; - int ct = 0; - - while(ct<nr) - { - u32 fspace = 0; - - /* - * Find the largest block we will fill going upwards - */ - - u32 high = power2(mem-top); - - /* - * Find the largest block we will fill going downwards - */ - - u32 low = base/2; - - /* - * Don't fill below 1Mb going downwards as there - * is an ISA hole in the way. - */ - - if(base <= 1024*1024) - low = 0; - - /* - * See how much space we could cover by filling below - * the ISA hole - */ - - if(floor == 0) - fspace = 512*1024; - else if(floor ==512*1024) - fspace = 128*1024; - - /* And forget ROM space */ - - /* - * Now install the largest coverage we get - */ - - if(fspace > high && fspace > low) - { - centaur_mcr_insert(ct, floor, fspace, key); - floor += fspace; - } - else if(high > low) - { - centaur_mcr_insert(ct, top, high, key); - top += high; - } - else if(low > 0) - { - base -= low; - centaur_mcr_insert(ct, base, low, key); - } - else break; - ct++; - } - /* - * We loaded ct values. We now need to set the mask. The caller - * must do this bit. - */ - - return ct; -} - -static void __init centaur_create_optimal_mcr(void) -{ - int i; - /* - * Allocate up to 6 mcrs to mark as much of ram as possible - * as write combining and weak write ordered. - * - * To experiment with: Linux never uses stack operations for - * mmio spaces so we could globally enable stack operation wc - * - * Load the registers with type 31 - full write combining, all - * writes weakly ordered. - */ - int used = centaur_mcr_compute(6, 31); - - /* - * Wipe unused MCRs - */ - - for(i=used;i<8;i++) - wrmsr(MSR_IDT_MCR0+i, 0, 0); -} - -static void __init winchip2_create_optimal_mcr(void) -{ - u32 lo, hi; - int i; - - /* - * Allocate up to 6 mcrs to mark as much of ram as possible - * as write combining, weak store ordered. - * - * Load the registers with type 25 - * 8 - weak write ordering - * 16 - weak read ordering - * 1 - write combining - */ - - int used = centaur_mcr_compute(6, 25); - - /* - * Mark the registers we are using. - */ - - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - for(i=0;i<used;i++) - lo|=1<<(9+i); - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); - - /* - * Wipe unused MCRs - */ - - for(i=used;i<8;i++) - wrmsr(MSR_IDT_MCR0+i, 0, 0); -} - -/* - * Handle the MCR key on the Winchip 2. - */ - -static void __init winchip2_unprotect_mcr(void) -{ - u32 lo, hi; - u32 key; - - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - lo&=~0x1C0; /* blank bits 8-6 */ - key = (lo>>17) & 7; - lo |= key<<6; /* replace with unlock key */ - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); -} - -static void __init winchip2_protect_mcr(void) -{ - u32 lo, hi; - - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - lo&=~0x1C0; /* blank bits 8-6 */ - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); -} -#endif /* CONFIG_X86_OOSTORE */ #define ACE_PRESENT (1 << 6) #define ACE_ENABLED (1 << 7) @@ -305,146 +63,12 @@ static void __init init_c3(struct cpuinf static void __init init_centaur(struct cpuinfo_x86 *c) { - enum { - ECX8=1<<1, - EIERRINT=1<<2, - DPM=1<<3, - DMCE=1<<4, - DSTPCLK=1<<5, - ELINEAR=1<<6, - DSMC=1<<7, - DTLOCK=1<<8, - EDCTLB=1<<8, - EMMX=1<<9, - DPDC=1<<11, - EBRPRED=1<<12, - DIC=1<<13, - DDC=1<<14, - DNA=1<<15, - ERETSTK=1<<16, - E2MMX=1<<19, - EAMD3D=1<<20, - }; - - char *name; - u32 fcr_set=0; - u32 fcr_clr=0; - u32 lo,hi,newlo; - u32 aa,bb,cc,dd; - /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, c->x86_capability); - switch (c->x86) { - - case 5: - switch(c->x86_model) { - case 4: - name="C6"; - fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK; - fcr_clr=DPDC; - printk(KERN_NOTICE "Disabling bugged TSC.\n"); - clear_bit(X86_FEATURE_TSC, c->x86_capability); -#ifdef CONFIG_X86_OOSTORE - centaur_create_optimal_mcr(); - /* Enable - write combining on non-stack, non-string - write combining on string, all types - weak write ordering - - The C6 original lacks weak read order - - Note 0x120 is write only on Winchip 1 */ - - wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); -#endif - break; - case 8: - switch(c->x86_mask) { - default: - name="2"; - break; - case 7 ... 9: - name="2A"; - break; - case 10 ... 15: - name="2B"; - break; - } - fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D; - fcr_clr=DPDC; -#ifdef CONFIG_X86_OOSTORE - winchip2_unprotect_mcr(); - winchip2_create_optimal_mcr(); - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - /* Enable - write combining on non-stack, non-string - write combining on string, all types - weak write ordering - */ - lo|=31; - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); - winchip2_protect_mcr(); -#endif - break; - case 9: - name="3"; - fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D; - fcr_clr=DPDC; -#ifdef CONFIG_X86_OOSTORE - winchip2_unprotect_mcr(); - winchip2_create_optimal_mcr(); - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - /* Enable - write combining on non-stack, non-string - write combining on string, all types - weak write ordering - */ - lo|=31; - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); - winchip2_protect_mcr(); -#endif - break; - case 10: - name="4"; - /* no info on the WC4 yet */ - break; - default: - name="??"; - } - - rdmsr(MSR_IDT_FCR1, lo, hi); - newlo=(lo|fcr_set) & (~fcr_clr); - - if (newlo!=lo) { - printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo ); - wrmsr(MSR_IDT_FCR1, newlo, hi ); - } else { - printk(KERN_INFO "Centaur FCR is 0x%X\n",lo); - } - /* Emulate MTRRs using Centaur's MCR. */ - set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability); - /* Report CX8 */ - set_bit(X86_FEATURE_CX8, c->x86_capability); - /* Set 3DNow! on Winchip 2 and above. */ - if (c->x86_model >=8) - set_bit(X86_FEATURE_3DNOW, c->x86_capability); - /* See if we can find out some more. */ - if ( cpuid_eax(0x80000000) >= 0x80000005 ) { - /* Yes, we can. */ - cpuid(0x80000005,&aa,&bb,&cc,&dd); - /* Add L1 data and code cache sizes. */ - c->x86_cache_size = (cc>>24)+(dd>>24); - } - snprintf( c->x86_model_id, sizeof(c->x86_model_id), - "WinChip %s", name ); - break; - - case 6: - init_c3(c); - break; - } + if (c->x86 == 6) + init_c3(c); } static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/common.c --- a/xen/arch/x86/cpu/common.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/x86/cpu/common.c Thu Sep 06 12:05:15 2007 -0600 @@ -524,7 +524,6 @@ extern int amd_init_cpu(void); extern int amd_init_cpu(void); extern int centaur_init_cpu(void); extern int transmeta_init_cpu(void); -extern int rise_init_cpu(void); void __init early_cpu_init(void) { @@ -535,7 +534,6 @@ void __init early_cpu_init(void) nsc_init_cpu(); centaur_init_cpu(); transmeta_init_cpu(); - rise_init_cpu(); #endif early_cpu_detect(); } diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/mtrr/Makefile --- a/xen/arch/x86/cpu/mtrr/Makefile Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/x86/cpu/mtrr/Makefile Thu Sep 06 12:05:15 2007 -0600 @@ -1,5 +1,4 @@ obj-$(x86_32) += amd.o obj-$(x86_32) += amd.o -obj-$(x86_32) += centaur.o obj-$(x86_32) += cyrix.o obj-y += generic.o obj-y += main.o diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/mtrr/centaur.c --- a/xen/arch/x86/cpu/mtrr/centaur.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -#include <xen/init.h> -#include <xen/mm.h> -#include <asm/mtrr.h> -#include <asm/msr.h> -#include "mtrr.h" - -static struct { - unsigned long high; - unsigned long low; -} centaur_mcr[8]; - -static u8 centaur_mcr_reserved; -static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */ - -/* - * Report boot time MCR setups - */ - -static int -centaur_get_free_region(unsigned long base, unsigned long size) -/* [SUMMARY] Get a free MTRR. - <base> The starting (base) address of the region. - <size> The size (in bytes) of the region. - [RETURNS] The index of the region on success, else -1 on error. -*/ -{ - int i, max; - mtrr_type ltype; - unsigned long lbase; - unsigned int lsize; - - max = num_var_ranges; - for (i = 0; i < max; ++i) { - if (centaur_mcr_reserved & (1 << i)) - continue; - mtrr_if->get(i, &lbase, &lsize, <ype); - if (lsize == 0) - return i; - } - return -ENOSPC; -} - -void -mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) -{ - centaur_mcr[mcr].low = lo; - centaur_mcr[mcr].high = hi; -} - -static void -centaur_get_mcr(unsigned int reg, unsigned long *base, - unsigned int *size, mtrr_type * type) -{ - *base = centaur_mcr[reg].high >> PAGE_SHIFT; - *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT; - *type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */ - if (centaur_mcr_type == 1 && ((centaur_mcr[reg].low & 31) & 2)) - *type = MTRR_TYPE_UNCACHABLE; - if (centaur_mcr_type == 1 && (centaur_mcr[reg].low & 31) == 25) - *type = MTRR_TYPE_WRBACK; - if (centaur_mcr_type == 0 && (centaur_mcr[reg].low & 31) == 31) - *type = MTRR_TYPE_WRBACK; - -} - -static void centaur_set_mcr(unsigned int reg, unsigned long base, - unsigned long size, mtrr_type type) -{ - unsigned long low, high; - - if (size == 0) { - /* Disable */ - high = low = 0; - } else { - high = base << PAGE_SHIFT; - if (centaur_mcr_type == 0) - low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */ - else { - if (type == MTRR_TYPE_UNCACHABLE) - low = -size << PAGE_SHIFT | 0x02; /* NC */ - else - low = -size << PAGE_SHIFT | 0x09; /* WWO,WC */ - } - } - centaur_mcr[reg].high = high; - centaur_mcr[reg].low = low; - wrmsr(MSR_IDT_MCR0 + reg, low, high); -} - -#if 0 -/* - * Initialise the later (saner) Winchip MCR variant. In this version - * the BIOS can pass us the registers it has used (but not their values) - * and the control register is read/write - */ - -static void __init -centaur_mcr1_init(void) -{ - unsigned i; - u32 lo, hi; - - /* Unfortunately, MCR's are read-only, so there is no way to - * find out what the bios might have done. - */ - - rdmsr(MSR_IDT_MCR_CTRL, lo, hi); - if (((lo >> 17) & 7) == 1) { /* Type 1 Winchip2 MCR */ - lo &= ~0x1C0; /* clear key */ - lo |= 0x040; /* set key to 1 */ - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); /* unlock MCR */ - } - - centaur_mcr_type = 1; - - /* - * Clear any unconfigured MCR's. - */ - - for (i = 0; i < 8; ++i) { - if (centaur_mcr[i].high == 0 && centaur_mcr[i].low == 0) { - if (!(lo & (1 << (9 + i)))) - wrmsr(MSR_IDT_MCR0 + i, 0, 0); - else - /* - * If the BIOS set up an MCR we cannot see it - * but we don't wish to obliterate it - */ - centaur_mcr_reserved |= (1 << i); - } - } - /* - * Throw the main write-combining switch... - * However if OOSTORE is enabled then people have already done far - * cleverer things and we should behave. - */ - - lo |= 15; /* Write combine enables */ - wrmsr(MSR_IDT_MCR_CTRL, lo, hi); -} - -/* - * Initialise the original winchip with read only MCR registers - * no used bitmask for the BIOS to pass on and write only control - */ - -static void __init -centaur_mcr0_init(void) -{ - unsigned i; - - /* Unfortunately, MCR's are read-only, so there is no way to - * find out what the bios might have done. - */ - - /* Clear any unconfigured MCR's. - * This way we are sure that the centaur_mcr array contains the actual - * values. The disadvantage is that any BIOS tweaks are thus undone. - * - */ - for (i = 0; i < 8; ++i) { - if (centaur_mcr[i].high == 0 && centaur_mcr[i].low == 0) - wrmsr(MSR_IDT_MCR0 + i, 0, 0); - } - - wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0); /* Write only */ -} - -/* - * Initialise Winchip series MCR registers - */ - -static void __init -centaur_mcr_init(void) -{ - struct set_mtrr_context ctxt; - - set_mtrr_prepare_save(&ctxt); - set_mtrr_cache_disable(&ctxt); - - if (boot_cpu_data.x86_model == 4) - centaur_mcr0_init(); - else if (boot_cpu_data.x86_model == 8 || boot_cpu_data.x86_model == 9) - centaur_mcr1_init(); - - set_mtrr_done(&ctxt); -} -#endif - -static int centaur_validate_add_page(unsigned long base, - unsigned long size, unsigned int type) -{ - /* - * FIXME: Winchip2 supports uncached - */ - if (type != MTRR_TYPE_WRCOMB && - (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE)) { - printk(KERN_WARNING - "mtrr: only write-combining%s supported\n", - centaur_mcr_type ? " and uncacheable are" - : " is"); - return -EINVAL; - } - return 0; -} - -static struct mtrr_ops centaur_mtrr_ops = { - .vendor = X86_VENDOR_CENTAUR, -// .init = centaur_mcr_init, - .set = centaur_set_mcr, - .get = centaur_get_mcr, - .get_free_region = centaur_get_free_region, - .validate_add_page = centaur_validate_add_page, - .have_wrcomb = positive_have_wrcomb, -}; - -int __init centaur_init_mtrr(void) -{ - set_mtrr_ops(¢aur_mtrr_ops); - return 0; -} - -//arch_initcall(centaur_init_mtrr); diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/mtrr/main.c --- a/xen/arch/x86/cpu/mtrr/main.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/x86/cpu/mtrr/main.c Thu Sep 06 12:05:15 2007 -0600 @@ -539,14 +539,12 @@ EXPORT_SYMBOL(mtrr_del); */ extern void amd_init_mtrr(void); extern void cyrix_init_mtrr(void); -extern void centaur_init_mtrr(void); static void __init init_ifs(void) { #ifndef CONFIG_X86_64 amd_init_mtrr(); cyrix_init_mtrr(); - centaur_init_mtrr(); #endif } @@ -609,13 +607,6 @@ void __init mtrr_bp_init(void) size_and_mask = 0; } break; - case X86_VENDOR_CENTAUR: - if (cpu_has_centaur_mcr) { - mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR]; - size_or_mask = 0xfff00000; /* 32 bits */ - size_and_mask = 0; - } - break; case X86_VENDOR_CYRIX: if (cpu_has_cyrix_arr) { mtrr_if = mtrr_ops[X86_VENDOR_CYRIX]; diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/cpu/rise.c --- a/xen/arch/x86/cpu/rise.c Thu Sep 06 09:05:26 2007 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -#include <xen/config.h> -#include <xen/lib.h> -#include <xen/init.h> -#include <xen/bitops.h> -#include <asm/processor.h> - -#include "cpu.h" - -static void __init init_rise(struct cpuinfo_x86 *c) -{ - printk("CPU: Rise iDragon"); - if (c->x86_model > 2) - printk(" II"); - printk("\n"); - - /* Unhide possibly hidden capability flags - The mp6 iDragon family don't have MSRs. - We switch on extra features with this cpuid weirdness: */ - __asm__ ( - "movl $0x6363452a, %%eax\n\t" - "movl $0x3231206c, %%ecx\n\t" - "movl $0x2a32313a, %%edx\n\t" - "cpuid\n\t" - "movl $0x63634523, %%eax\n\t" - "movl $0x32315f6c, %%ecx\n\t" - "movl $0x2333313a, %%edx\n\t" - "cpuid\n\t" : : : "eax", "ebx", "ecx", "edx" - ); - set_bit(X86_FEATURE_CX8, c->x86_capability); -} - -static struct cpu_dev rise_cpu_dev __initdata = { - .c_vendor = "Rise", - .c_ident = { "RiseRiseRise" }, - .c_models = { - { .vendor = X86_VENDOR_RISE, .family = 5, .model_names = - { - [0] = "iDragon", - [2] = "iDragon", - [8] = "iDragon II", - [9] = "iDragon II" - } - }, - }, - .c_init = init_rise, -}; - -int __init rise_init_cpu(void) -{ - cpu_devs[X86_VENDOR_RISE] = &rise_cpu_dev; - return 0; -} - -//early_arch_initcall(rise_init_cpu); diff -r 12be90e2f831 -r 4ffca478e2f7 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Thu Sep 06 09:05:26 2007 -0600 +++ b/xen/arch/x86/domain.c Thu Sep 06 12:05:15 2007 -0600 @@ -437,6 +437,9 @@ int arch_domain_create(struct domain *d) int vcpuid, pdpt_order, paging_initialised = 0; int rc = -ENOMEM; + d->arch.relmem = RELMEM_not_started; + INIT_LIST_HEAD(&d->arch.relmem_list); + pdpt_order = get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t)); d->arch.mm_perdomain_pt = alloc_xenheap_pages(pdpt_order); if ( d->arch.mm_perdomain_pt == NULL ) @@ -1599,12 +1602,13 @@ int hypercall_xlat_continuation(unsigned } #endif -static void relinquish_memory(struct domain *d, struct list_head *list, - unsigned long type) +static int relinquish_memory( + struct domain *d, struct list_head *list, unsigned long type) { struct list_head *ent; struct page_info *page; unsigned long x, y; + int ret = 0; /* Use a recursive lock, as we may enter 'free_domheap_page'. */ spin_lock_recursive(&d->page_alloc_lock); @@ -1619,6 +1623,7 @@ static void relinquish_memory(struct dom { /* Couldn't get a reference -- someone is freeing this page. */ ent = ent->next; + list_move_tail(&page->list, &d->arch.relmem_list); continue; } @@ -1653,10 +1658,21 @@ static void relinquish_memory(struct dom /* Follow the list chain and /then/ potentially free the page. */ ent = ent->next; + list_move_tail(&page->list, &d->arch.relmem_list); put_page(page); - } - + + if ( hypercall_preempt_check() ) + { + ret = -EAGAIN; + goto out; + } + } + + list_splice_init(&d->arch.relmem_list, list); + + out: spin_unlock_recursive(&d->page_alloc_lock); + return ret; } static void vcpu_destroy_pagetables(struct vcpu *v) @@ -1717,43 +1733,91 @@ static void vcpu_destroy_pagetables(stru v->arch.cr3 = 0; } -void domain_relinquish_resources(struct domain *d) -{ +int domain_relinquish_resources(struct domain *d) +{ + int ret; struct vcpu *v; BUG_ON(!cpus_empty(d->domain_dirty_cpumask)); - /* Drop the in-use references to page-table bases. */ - for_each_vcpu ( d, v ) - vcpu_destroy_pagetables(v); - - /* Tear down paging-assistance stuff. */ - paging_teardown(d); - - /* - * Relinquish GDT mappings. No need for explicit unmapping of the LDT as - * it automatically gets squashed when the guest's mappings go away. - */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |