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