aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-08-31 11:21:35 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-08-31 11:21:35 +0100
commitd046f361dc937d8fc179cc2da168f571726cb5a0 (patch)
tree578473169c1d081d7e3ed825d926377e4b8b9226 /xen
parent3d030c1164e2c7bfc4873368e14bae9cc0e23e16 (diff)
downloadxen-d046f361dc937d8fc179cc2da168f571726cb5a0.tar.gz
xen-d046f361dc937d8fc179cc2da168f571726cb5a0.tar.bz2
xen-d046f361dc937d8fc179cc2da168f571726cb5a0.zip
Xen Security Modules: XSM
Signed-off-by: George Coker <gscoker@alpha.ncsc.mil>
Diffstat (limited to 'xen')
-rw-r--r--xen/Makefile3
-rw-r--r--xen/Rules.mk2
-rw-r--r--xen/arch/x86/domctl.c56
-rw-r--r--xen/arch/x86/hvm/hvm.c16
-rw-r--r--xen/arch/x86/mm.c35
-rw-r--r--xen/arch/x86/mm/paging.c5
-rw-r--r--xen/arch/x86/physdev.c11
-rw-r--r--xen/arch/x86/platform_hypercall.c27
-rw-r--r--xen/arch/x86/setup.c3
-rw-r--r--xen/arch/x86/sysctl.c5
-rw-r--r--xen/arch/x86/x86_32/entry.S2
-rw-r--r--xen/arch/x86/x86_32/xen.lds.S2
-rw-r--r--xen/arch/x86/x86_64/entry.S2
-rw-r--r--xen/common/domain.c12
-rw-r--r--xen/common/domctl.c99
-rw-r--r--xen/common/event_channel.c46
-rw-r--r--xen/common/grant_table.c47
-rw-r--r--xen/common/kexec.c5
-rw-r--r--xen/common/memory.c25
-rw-r--r--xen/common/schedule.c8
-rw-r--r--xen/common/sysctl.c21
-rw-r--r--xen/common/xenoprof.c5
-rw-r--r--xen/drivers/char/console.c5
-rw-r--r--xen/include/public/xen.h1
-rw-r--r--xen/include/xen/hypercall.h5
-rw-r--r--xen/include/xsm/xsm.h537
-rw-r--r--xen/xsm/Makefile5
-rw-r--r--xen/xsm/dummy.c488
-rw-r--r--xen/xsm/xsm_core.c118
-rw-r--r--xen/xsm/xsm_policy.c67
30 files changed, 1661 insertions, 2 deletions
diff --git a/xen/Makefile b/xen/Makefile
index b0a9ac311c..456003ebb9 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -56,6 +56,7 @@ _clean: delete-unfresh-files
$(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 +123,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
build-headers:
$(MAKE) -C include/public/foreign
-SUBDIRS = acm arch/$(TARGET_ARCH) common drivers
+SUBDIRS = xsm acm 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 --git a/xen/Rules.mk b/xen/Rules.mk
index 55ae9746e0..dd78419dea 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -52,10 +52,12 @@ HDRS := $(filter-out %/asm-offsets.h,$(AHDRS))
# Note that link order matters!
ALL_OBJS-y += $(BASEDIR)/common/built_in.o
ALL_OBJS-y += $(BASEDIR)/drivers/built_in.o
+ALL_OBJS-y += $(BASEDIR)/xsm/built_in.o
ALL_OBJS-$(ACM_SECURITY) += $(BASEDIR)/acm/built_in.o
ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o
CFLAGS-y += -g -D__XEN__
+CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE
CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY
CFLAGS-$(verbose) += -DVERBOSE
CFLAGS-$(crash_debug) += -DCRASH_DEBUG
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index a42efee417..40871491ae 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -24,6 +24,7 @@
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/processor.h>
+#include <xsm/xsm.h>
long arch_do_domctl(
struct xen_domctl *domctl,
@@ -64,6 +65,14 @@ long arch_do_domctl(
if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
break;
+ ret = xsm_ioport_permission(d, fp,
+ domctl->u.ioport_permission.allow_access);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
if ( np == 0 )
ret = 0;
else if ( domctl->u.ioport_permission.allow_access )
@@ -90,6 +99,13 @@ long arch_do_domctl(
page = mfn_to_page(mfn);
+ ret = xsm_getpageframeinfo(page);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
if ( likely(get_page(page, d)) )
{
ret = 0;
@@ -173,6 +189,10 @@ long arch_do_domctl(
page = mfn_to_page(mfn);
+ ret = xsm_getpageframeinfo(page);
+ if ( ret )
+ continue;
+
if ( likely(mfn_valid(mfn) && get_page(page, d)) )
{
unsigned long type = 0;
@@ -230,6 +250,13 @@ long arch_do_domctl(
ret = -EINVAL;
if ( d != NULL )
{
+ ret = xsm_getmemlist(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
ret = 0;
spin_lock(&d->page_alloc_lock);
@@ -269,6 +296,13 @@ long arch_do_domctl(
if ( unlikely(d == NULL) )
break;
+ ret = xsm_hypercall_init(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
mfn = gmfn_to_mfn(d, gmfn);
ret = -EACCES;
@@ -304,6 +338,10 @@ long arch_do_domctl(
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
+ ret = xsm_hvmcontext(d, domctl->cmd);
+ if ( ret )
+ goto sethvmcontext_out;
+
ret = -EINVAL;
if ( !is_hvm_domain(d) )
goto sethvmcontext_out;
@@ -337,6 +375,10 @@ long arch_do_domctl(
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
+ ret = xsm_hvmcontext(d, domctl->cmd);
+ if ( ret )
+ goto gethvmcontext_out;
+
ret = -EINVAL;
if ( !is_hvm_domain(d) )
goto gethvmcontext_out;
@@ -390,6 +432,13 @@ long arch_do_domctl(
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
+ ret = xsm_address_size(d, domctl->cmd);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
switch ( domctl->u.address_size.size )
{
#ifdef CONFIG_COMPAT
@@ -417,6 +466,13 @@ long arch_do_domctl(
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
+ ret = xsm_address_size(d, domctl->cmd);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
domctl->u.address_size.size = BITS_PER_GUEST_LONG(d);
ret = 0;
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 91b5640e54..fa9752cd78 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1069,6 +1069,10 @@ static int hvmop_set_pci_intx_level(
if ( !is_hvm_domain(d) )
goto out;
+ rc = xsm_hvm_set_pci_intx_level(d);
+ if ( rc )
+ goto out;
+
rc = 0;
switch ( op.level )
{
@@ -1112,6 +1116,10 @@ static int hvmop_set_isa_irq_level(
if ( !is_hvm_domain(d) )
goto out;
+ rc = xsm_hvm_set_isa_irq_level(d);
+ if ( rc )
+ goto out;
+
rc = 0;
switch ( op.level )
{
@@ -1155,6 +1163,10 @@ static int hvmop_set_pci_link_route(
if ( !is_hvm_domain(d) )
goto out;
+ rc = xsm_hvm_set_pci_link_route(d);
+ if ( rc )
+ goto out;
+
rc = 0;
hvm_set_pci_link_route(d, op.link, op.isa_irq);
@@ -1204,6 +1216,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
if ( !is_hvm_domain(d) )
goto param_fail;
+ rc = xsm_hvm_param(d, op);
+ if ( rc )
+ goto param_fail;
+
if ( op == HVMOP_set_param )
{
switch ( a.index )
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 5ff93f4d34..53c01dc1b4 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -110,6 +110,7 @@
#include <asm/hypercall.h>
#include <asm/shared.h>
#include <public/memory.h>
+#include <xsm/xsm.h>
#define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
@@ -2048,6 +2049,10 @@ int do_mmuext_op(
type = PGT_l4_page_table;
pin_page:
+ rc = xsm_memory_pin_page(current->domain, page);
+ if ( rc )
+ break;
+
/* Ignore pinning of invalid paging levels. */
if ( (op.cmd - MMUEXT_PIN_L1_TABLE) > (CONFIG_PAGING_LEVELS - 1) )
break;
@@ -2334,6 +2339,10 @@ int do_mmu_update(
*/
case MMU_NORMAL_PT_UPDATE:
+ rc = xsm_mmu_normal_update(current->domain, req.val);
+ if ( rc )
+ break;
+
gmfn = req.ptr >> PAGE_SHIFT;
mfn = gmfn_to_mfn(d, gmfn);
@@ -2424,6 +2433,10 @@ int do_mmu_update(
mfn = req.ptr >> PAGE_SHIFT;
gpfn = req.val;
+ rc = xsm_mmu_machphys_update(current->domain, mfn);
+ if ( rc )
+ break;
+
if ( unlikely(!get_page_from_pagenr(mfn, FOREIGNDOM)) )
{
MEM_LOG("Could not get page for mach->phys update");
@@ -2802,6 +2815,10 @@ int do_update_va_mapping(unsigned long va, u64 val64,
if ( unlikely(!__addr_ok(va) && !paging_mode_external(d)) )
return -EINVAL;
+ rc = xsm_update_va_mapping(current->domain, val);
+ if ( rc )
+ return rc;
+
LOCK_BIGLOCK(d);
pl1e = guest_map_l1e(v, va, &gl1mfn);
@@ -3063,6 +3080,12 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
else if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
return -ESRCH;
+ if ( xsm_add_to_physmap(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
+ }
+
switch ( xatp.space )
{
case XENMAPSPACE_shared_info:
@@ -3139,6 +3162,13 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
else if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
return -ESRCH;
+ rc = xsm_domain_memory_map(d);
+ if ( rc )
+ {
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
rc = copy_from_guest(d->arch.e820, fmap.map.buffer,
fmap.map.nr_entries) ? -EFAULT : 0;
d->arch.nr_e820 = fmap.map.nr_entries;
@@ -3172,10 +3202,15 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
struct xen_memory_map memmap;
XEN_GUEST_HANDLE(e820entry_t) buffer;
int count;
+ int rc;
if ( !IS_PRIV(current->domain) )
return -EINVAL;
+ rc = xsm_machine_memory_map();
+ if ( rc )
+ return rc;
+
if ( copy_from_guest(&memmap, arg, 1) )
return -EFAULT;
if ( memmap.nr_entries < e820.nr_map + 1 )
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index ac4db900a5..25f323151d 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -26,6 +26,7 @@
#include <asm/p2m.h>
#include <asm/hap.h>
#include <asm/guest_access.h>
+#include <xsm/xsm.h>
/* Xen command-line option to enable hardware-assisted paging */
int opt_hap_enabled;
@@ -402,6 +403,10 @@ int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
return -EINVAL;
}
+ rc = xsm_shadow_control(d, sc->op);
+ if ( rc )
+ return rc;
+
/* Code to handle log-dirty. Note that some log dirty operations
* piggy-back on shadow operations. For example, when
* XEN_DOMCTL_SHADOW_OP_OFF is called, it first checks whether log dirty
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 7b9bfedb51..78ff6b0ca8 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -12,6 +12,7 @@
#include <asm/hypercall.h>
#include <public/xen.h>
#include <public/physdev.h>
+#include <xsm/xsm.h>
#ifndef COMPAT
typedef long ret_t;
@@ -73,6 +74,9 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
ret = -EPERM;
if ( !IS_PRIV(v->domain) )
break;
+ ret = xsm_apic(v->domain, cmd);
+ if ( ret )
+ break;
ret = ioapic_guest_read(apic.apic_physbase, apic.reg, &apic.value);
if ( copy_to_guest(arg, &apic, 1) != 0 )
ret = -EFAULT;
@@ -87,6 +91,9 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
ret = -EPERM;
if ( !IS_PRIV(v->domain) )
break;
+ ret = xsm_apic(v->domain, cmd);
+ if ( ret )
+ break;
ret = ioapic_guest_write(apic.apic_physbase, apic.reg, apic.value);
break;
}
@@ -102,6 +109,10 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
if ( !IS_PRIV(v->domain) )
break;
+ ret = xsm_assign_vector(v->domain, irq_op.irq);
+ if ( ret )
+ break;
+
irq = irq_op.irq;
ret = -EINVAL;
if ( (irq < 0) || (irq >= NR_IRQS) )
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index 6d1f019343..6228ea9671 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -24,6 +24,7 @@
#include <asm/edd.h>
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
+#include <xsm/xsm.h>
extern uint16_t boot_edid_caps;
extern uint8_t boot_edid_info[];
@@ -59,6 +60,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
{
case XENPF_settime:
{
+ ret = xsm_xen_settime();
+ if ( ret )
+ break;
+
do_settime(op->u.settime.secs,
op->u.settime.nsecs,
op->u.settime.system_time);
@@ -68,6 +73,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
case XENPF_add_memtype:
{
+ ret = xsm_memtype(op->cmd);
+ if ( ret )
+ break;
+
ret = mtrr_add_page(
op->u.add_memtype.mfn,
op->u.add_memtype.nr_mfns,
@@ -86,6 +95,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
case XENPF_del_memtype:
{
+ ret = xsm_memtype(op->cmd);
+ if ( ret )
+ break;
+
if (op->u.del_memtype.handle == 0
/* mtrr/main.c otherwise does a lookup */
&& (int)op->u.del_memtype.reg >= 0)
@@ -105,6 +118,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
unsigned int nr_mfns;
mtrr_type type;
+ ret = xsm_memtype(op->cmd);
+ if ( ret )
+ break;
+
ret = -EINVAL;
if ( op->u.read_memtype.reg < num_var_ranges )
{
@@ -120,6 +137,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
case XENPF_microcode_update:
{
extern int microcode_update(XEN_GUEST_HANDLE(void), unsigned long len);
+
+ ret = xsm_microcode();
+ if ( ret )
+ break;
+
#ifndef COMPAT
ret = microcode_update(op->u.microcode.data,
op->u.microcode.length);
@@ -136,6 +158,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
{
extern int opt_noirqbalance;
int quirk_id = op->u.platform_quirk.quirk_id;
+
+ ret = xsm_platform_quirk(quirk_id);
+ if ( ret )
+ break;
+
switch ( quirk_id )
{
case QUIRK_NOIRQBALANCING:
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 31d669a207..fcc5073fce 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -35,6 +35,7 @@
#include <acm/acm_hooks.h>
#include <xen/kexec.h>
#include <asm/edd.h>
+#include <xsm/xsm.h>
#if defined(CONFIG_X86_64)
#define BOOTSTRAP_DIRECTMAP_END (1UL << 32) /* 4GB */
@@ -963,6 +964,8 @@ void __init __start_xen(unsigned long mbi_p)
percpu_init_areas();
+ xsm_init(&initrdidx, mbi, initial_images_start);
+
init_idle_domain();
trap_init();
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index ff7018a930..e518d4ce49 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -25,6 +25,7 @@
#include <asm/processor.h>
#include <asm/numa.h>
#include <xen/nodemask.h>
+#include <xsm/xsm.h>
#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
@@ -42,6 +43,10 @@ long arch_do_sysctl(
xen_sysctl_physinfo_t *pi = &sysctl->u.physinfo;
+ ret = xsm_physinfo();
+ if ( ret )
+ break;
+
pi->threads_per_core =
cpus_weight(cpu_sibling_map[0]);
pi->cores_per_socket =
diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S
index 8ca596e15f..6f243b8d1b 100644
--- a/xen/arch/x86/x86_32/entry.S
+++ b/xen/arch/x86/x86_32/entry.S
@@ -676,6 +676,7 @@ ENTRY(hypercall_table)
.long do_sysctl /* 35 */
.long do_domctl
.long do_kexec_op
+ .long do_xsm_op
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
@@ -719,6 +720,7 @@ ENTRY(hypercall_args_table)
.byte 1 /* do_sysctl */ /* 35 */
.byte 1 /* do_domctl */
.byte 2 /* do_kexec_op */
+ .byte 1 /* do_xsm_op */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
diff --git a/xen/arch/x86/x86_32/xen.lds.S b/xen/arch/x86/x86_32/xen.lds.S
index d59cff95c4..08649f931b 100644
--- a/xen/arch/x86/x86_32/xen.lds.S
+++ b/xen/arch/x86/x86_32/xen.lds.S
@@ -63,6 +63,8 @@ SECTIONS
__initcall_start = .;
.initcall.init : { *(.initcall1.init) } :text
__initcall_end = .;
+ .xsm_initcall.init : { __xsm_initcall_start = .;
+ *(.xsm_initcall.init) __xsm_initcall_end = .; }
. = ALIGN(PAGE_SIZE);
__init_end = .;
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index 0bef33070e..69f2725304 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -612,6 +612,7 @@ ENTRY(hypercall_table)
.quad do_sysctl /* 35 */
.quad do_domctl
.quad do_kexec_op
+ .quad do_xsm_op
.rept NR_hypercalls-((.-hypercall_table)/8)
.quad do_ni_hypercall
.endr
@@ -655,6 +656,7 @@ ENTRY(hypercall_args_table)
.byte 1 /* do_sysctl */ /* 35 */
.byte 1 /* do_domctl */
.byte 2 /* do_kexec */
+ .byte 1 /* do_xsm_op */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 1a8937f1e1..b7f68a236f 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -29,6 +29,7 @@
#include <public/sched.h>
#include <public/vcpu.h>
#include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
/* Protect updates/reads (resp.) of domain_list and domain_hash. */
DEFINE_SPINLOCK(domlist_update_lock);
@@ -57,6 +58,13 @@ struct domain *alloc_domain(domid_t domid)
memset(d, 0, sizeof(*d));
d->domain_id = domid;
+
+ if ( xsm_alloc_security_domain(d) != 0 )
+ {
+ free_domain(d);
+ return NULL;
+ }
+
atomic_set(&d->refcnt, 1);
spin_lock_init(&d->big_lock);
spin_lock_init(&d->page_alloc_lock);
@@ -69,6 +77,7 @@ struct domain *alloc_domain(domid_t domid)
void free_domain(struct domain *d)
{
+ xsm_free_security_domain(d);
xfree(d);
}
@@ -193,6 +202,9 @@ struct domain *domain_create(
if ( !is_idle_domain(d) )
{
+ if ( xsm_domain_create(d, ssidref) != 0 )
+ goto fail;
+
d->is_paused_by_controller = 1;
atomic_inc(&d->pause_count);
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 5d29667b7c..c1c391e82d 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -24,6 +24,7 @@
#include <asm/current.h>
#include <public/domctl.h>
#include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
extern long arch_do_domctl(
struct xen_domctl *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
@@ -127,7 +128,9 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
else
info->ssidref = ACM_DEFAULT_SSID;
-
+
+ xsm_security_domaininfo(d, info);
+
info->tot_pages = d->tot_pages;
info->max_pages = d->max_pages;
info->shared_info_frame = mfn_to_gmfn(d, __pa(d->shared_info)>>PAGE_SHIFT);
@@ -204,6 +207,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_setvcpucontext(d);
+ if ( ret )
+ goto svc_out;
+
ret = -EINVAL;
if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
goto svc_out;
@@ -251,12 +258,17 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
ret = -ESRCH;
if ( d != NULL )
{
+ ret = xsm_pausedomain(d);
+ if ( ret )
+ goto pausedomain_out;
+
ret = -EINVAL;
if ( d != current->domain )
{
domain_pause_by_systemcontroller(d);
ret = 0;
}
+ pausedomain_out:
rcu_unlock_domain(d);
}
}
@@ -270,6 +282,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_unpausedomain(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
domain_unpause_by_systemcontroller(d);
rcu_unlock_domain(d);
ret = 0;
@@ -284,6 +303,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_resumedomain(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
domain_resume(d);
rcu_unlock_domain(d);
ret = 0;
@@ -359,6 +385,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
+ ret = xsm_max_vcpus(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
/* Needed, for example, to ensure writable p.t. state is synced. */
domain_pause(d);
@@ -395,12 +428,18 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
ret = -ESRCH;
if ( d != NULL )
{
+ ret = xsm_destroydomain(d);
+ if ( ret )
+ goto destroydomain_out;
+
ret = -EINVAL;
if ( d != current->domain )
{
domain_kill(d);
ret = 0;
}
+
+ destroydomain_out:
rcu_unlock_domain(d);
}
}
@@ -418,6 +457,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_vcpuaffinity(op->cmd, d);
+ if ( ret )
+ goto vcpuaffinity_out;
+
ret = -EINVAL;
if ( op->u.vcpuaffinity.vcpu >= MAX_VIRT_CPUS )
goto vcpuaffinity_out;
@@ -452,10 +495,15 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
+ ret = xsm_scheduler(d);
+ if ( ret )
+ goto scheduler_op_out;
+
ret = sched_adjust(d, &op->u.scheduler_op);
if ( copy_to_guest(u_domctl, op, 1) )
ret = -EFAULT;
+ scheduler_op_out:
rcu_unlock_domain(d);
}
break;
@@ -478,12 +526,17 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
break;
}
+ ret = xsm_getdomaininfo(d);
+ if ( ret )
+ goto getdomaininfo_out;
+
getdomaininfo(d, &op->u.getdomaininfo);
op->domain = op->u.getdomaininfo.domain;
if ( copy_to_guest(u_domctl, op, 1) )
ret = -EFAULT;
+ getdomaininfo_out:
rcu_read_unlock(&domlist_read_lock);
}
break;
@@ -498,6 +551,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
+ ret = xsm_getvcpucontext(d);
+ if ( ret )
+ goto getvcpucontext_out;
+
ret = -EINVAL;
if ( op->u.vcpucontext.vcpu >= MAX_VIRT_CPUS )
goto getvcpucontext_out;
@@ -554,6 +611,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
break;
+ ret = xsm_getvcpuinfo(d);
+ if ( ret )
+ goto getvcpuinfo_out;
+
ret = -EINVAL;
if ( op->u.getvcpuinfo.vcpu >= MAX_VIRT_CPUS )
goto getvcpuinfo_out;
@@ -589,6 +650,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_setdomainmaxmem(d);
+ if ( ret )
+ goto max_mem_out;
+
ret = -EINVAL;
new_max = op->u.max_mem.max_memkb >> (PAGE_SHIFT-10);
@@ -603,6 +668,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
}
spin_unlock(&d->page_alloc_lock);
+ max_mem_out:
rcu_unlock_domain(d);
}
break;
@@ -616,6 +682,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_setdomainhandle(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
memcpy(d->handle, op->u.setdomainhandle.handle,
sizeof(xen_domain_handle_t));
rcu_unlock_domain(d);
@@ -632,6 +705,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_setdebugging(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
domain_pause(d);
d->debugger_attached = !!op->u.setdebugging.enable;
domain_unpause(d); /* causes guest to latch new status */
@@ -654,11 +734,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_irq_permission(d, pirq, op->u.irq_permission.allow_access);
+ if ( ret )
+ goto irq_permission_out;
+
if ( op->u.irq_permission.allow_access )
ret = irq_permit_access(d, pirq);
else
ret = irq_deny_access(d, pirq);
+ irq_permission_out:
rcu_unlock_domain(d);
}
break;
@@ -678,11 +763,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
+ ret = xsm_iomem_permission(d, mfn, op->u.iomem_permission.allow_access);
+ if ( ret )
+ goto iomem_permission_out;
+
if ( op->u.iomem_permission.allow_access )
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
else
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
+ iomem_permission_out:
rcu_unlock_domain(d);
}
break;
@@ -695,6 +785,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
d = rcu_lock_domain_by_id(op->domain);
if ( d != NULL )
{
+ ret = xsm_domain_settime(d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ break;
+ }
+
d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
rcu_unlock_domain(d);
ret = 0;
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 09533a0e14..145a238ccf 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -30,6 +30,7 @@
#include <public/xen.h>
#include <public/event_channel.h>
#include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
#define bucket_from_port(d,p) \
((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])
@@ -78,6 +79,7 @@ static int get_free_port(struct domain *d)
{
struct evtchn *chn;
int port;
+ int i, j;
if ( d->is_dying )
return -EINVAL;
@@ -95,6 +97,19 @@ static int get_free_port(struct domain *d)
memset(chn, 0, EVTCHNS_PER_BUCKET * sizeof(*chn));
bucket_from_port(d, port) = chn;
+ for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
+ {
+ if ( xsm_alloc_security_evtchn(&chn[i]) )
+ {
+ for ( j = 0; j < i; j++ )
+ {
+ xsm_free_security_evtchn(&chn[j]);
+ }
+ xfree(chn);
+ return -ENOMEM;
+ }
+ }
+
return port;
}
@@ -124,6 +139,10 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
ERROR_EXIT(port);
chn = evtchn_from_port(d, port);
+ rc = xsm_evtchn_unbound(d, chn, alloc->remote_dom);
+ if ( rc )
+ goto out;
+
chn->state = ECS_UNBOUND;
if ( (chn->u.unbound.remote_domid = alloc->remote_dom) == DOMID_SELF )
chn->u.unbound.remote_domid = current->domain->domain_id;
@@ -180,6 +199,10 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
(rchn->u.unbound.remote_domid != ld->domain_id) )
ERROR_EXIT(-EINVAL);
+ rc = xsm_evtchn_interdomain(ld, lchn, rd, rchn);
+ if ( rc )
+ goto out;
+
lchn->u.interdomain.remote_dom = rd;
lchn->u.interdomain.remote_port = (u16)rport;
lchn->state = ECS_INTERDOMAIN;
@@ -422,6 +445,8 @@ static long __evtchn_close(struct domain *d1, int port1)
chn1->state = ECS_FREE;
chn1->notify_vcpu_id = 0;
+ xsm_evtchn_close_post(chn1);
+
out:
if ( d2 != NULL )
{
@@ -466,6 +491,10 @@ long evtchn_send(unsigned int lport)
return -EINVAL;
}
+ ret = xsm_evtchn_send(ld, lchn);
+ if ( ret )
+ goto out;
+
switch ( lchn->state )
{
case ECS_INTERDOMAIN:
@@ -495,6 +524,7 @@ long evtchn_send(unsigned int lport)
ret = -EINVAL;
}
+out:
spin_unlock(&ld->evtchn_lock);
return ret;
@@ -613,6 +643,11 @@ static long evtchn_status(evtchn_status_t *status)
}
chn = evtchn_from_port(d, port);
+
+ rc = xsm_evtchn_status(d, chn);
+ if ( rc )
+ goto out;
+
switch ( chn->state )
{
case ECS_FREE:
@@ -743,6 +778,7 @@ static long evtchn_reset(evtchn_reset_t *r)
domid_t dom = r->dom;
struct domain *d;
int i;
+ int rc;
if ( dom == DOMID_SELF )
dom = current->domain->domain_id;
@@ -752,6 +788,13 @@ static long evtchn_reset(evtchn_reset_t *r)
if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
return -ESRCH;
+ rc = xsm_evtchn_reset(current->domain, d);
+ if ( rc )
+ {
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
for ( i = 0; port_is_valid(d, i); i++ )
(void)__evtchn_close(d, i);
@@ -969,7 +1012,10 @@ void evtchn_destroy(struct domain *d)
/* Free all event-channel buckets. */
spin_lock(&d->evtchn_lock);
for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ )
+ {
+ xsm_free_security_evtchn(d->evtchn[i]);
xfree(d->evtchn[i]);
+ }
spin_unlock(&d->evtchn_lock);
}
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 8df6fb1cc1..e240452f14 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -33,6 +33,7 @@
#include <xen/guest_access.h>
#include <xen/domain_page.h>
#include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
#ifndef max_nr_grant_frames
unsigned int max_nr_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES;
@@ -224,6 +225,14 @@ __gnttab_map_grant_ref(
return;
}
+ rc = xsm_grant_mapref(ld, rd, op->flags);
+ if ( rc )
+ {
+ rcu_unlock_domain(rd);
+ op->status = GNTST_permission_denied;
+ return;
+ }
+
if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
{
rcu_unlock_domain(rd);
@@ -451,6 +460,14 @@ __gnttab_unmap_common(
return;
}
+ rc = xsm_grant_unmapref(ld, rd);
+ if ( rc )
+ {
+ rcu_unlock_domain(rd);
+ op->status = GNTST_permission_denied;
+ return;
+ }
+
TRACE_1D(TRC_MEM_PAGE_GRANT_UNMAP, dom);
spin_lock(&rd->grant_table->lock);
@@ -705,6 +722,13 @@ gnttab_setup_table(
goto out;
}
+ if ( xsm_grant_setup(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ op.status = GNTST_permission_denied;
+ goto out;
+ }
+
spin_lock(&d->grant_table->lock);
if ( (op.nr_frames > nr_grant_frames(d->grant_table)) &&
@@ -745,6 +769,7 @@ gnttab_query_size(
struct gnttab_query_size op;
struct domain *d;
domid_t dom;
+ int rc;
if ( count != 1 )
return -EINVAL;
@@ -773,6 +798,14 @@ gnttab_query_size(
goto query_out;
}
+ rc = xsm_grant_query_size(current->domain, d);
+ if ( rc )
+ {
+ rcu_unlock_domain(d);
+ op.status = GNTST_permission_denied;
+ goto query_out;
+ }
+
spin_lock(&d->grant_table->lock);
op.nr_frames = nr_grant_frames(d->grant_table);
@@ -919,6 +952,13 @@ gnttab_transfer(
goto copyback;
}
+ if ( xsm_grant_transfer(d, e) )
+ {
+ rcu_unlock_domain(e);
+ gop.status = GNTST_permission_denied;
+ goto copyback;
+ }
+
spin_lock(&e->page_alloc_lock);
/*
@@ -1139,6 +1179,13 @@ __gnttab_copy(
PIN_FAIL(error_out, GNTST_bad_domain,
"couldn't find %d\n", op->dest.domid);
+ rc = xsm_grant_copy(sd, dd);
+ if ( rc )
+ {
+ rc = GNTST_permission_denied;
+ goto error_out;
+ }
+
if ( src_is_gref )
{
rc = __acquire_grant_for_copy(sd, op->source.u.ref, 1, &s_frame);
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 2437799d63..4e95cf319d 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -21,6 +21,7 @@
#include <xen/version.h>
#include <xen/console.h>
#include <public/elfnote.h>
+#include <xsm/xsm.h>
#ifndef COMPAT
@@ -367,6 +368,10 @@ ret_t do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
if ( !IS_PRIV(current->domain) )
return -EPERM;
+ ret = xsm_kexec();
+ if ( ret )
+ return ret;
+
switch ( op )
{
case KEXEC_CMD_kexec_get_range:
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 311c5ae123..783de29749 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -22,6 +22,7 @@
#include <asm/current.h>
#include <asm/hardirq.h>
#include <public/memory.h>
+#include <xsm/xsm.h>
struct memop_args {
/* INPUT */
@@ -216,6 +217,7 @@ static long translate_gpfn_list(
xen_pfn_t gpfn;
xen_pfn_t mfn;
struct domain *d;
+ int rc;
if ( copy_from_guest(&op, uop, 1) )
return -EFAULT;
@@ -259,6 +261,13 @@ static long translate_gpfn_list(
mfn = gmfn_to_mfn(d, gpfn);
+ rc = xsm_translate_gpfn_list(current->domain, mfn);
+ if ( rc )
+ {
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
if ( unlikely(__copy_to_guest_offset(op.mfn_list, i, &mfn, 1)) )
{
rcu_unlock_domain(d);
@@ -538,6 +547,14 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
return start_extent;
args.domain = d;
+ rc = xsm_memory_adjust_reservation(current->domain, d);
+ if ( rc )
+ {
+ if ( reservation.domid != DOMID_SELF )
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
switch ( op )
{
case XENMEM_increase_reservation:
@@ -584,6 +601,14 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
return -ESRCH;
+ rc = xsm_memory_stat_reservation(current->domain, d);
+ if ( rc )
+ {
+ if ( domid != DOMID_SELF )
+ rcu_unlock_domain(d);
+ return rc;
+ }
+
switch ( op )
{
case XENMEM_current_reservation:
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index 7911f5f99c..50aacafb61 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -32,6 +32,7 @@
#include <xen/guest_access.h>
#include <xen/multicall.h>
#include <public/sched.h>
+#include <xsm/xsm.h>
/* opt_sched: scheduler - default to credit */
static char opt_sched[10] = "credit";
@@ -461,6 +462,13 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
if ( d == NULL )
break;
+ ret = xsm_schedop_shutdown(current->domain, d);
+ if ( ret )
+ {
+ rcu_unlock_domain(d);
+ return ret;
+ }
+
/* domain_pause() prevens any further execution in guest context. */
domain_pause(d);
domain_shutdown(d, (u8)sched_remote_shutdown.reason);
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index 98d3777e0a..39d0d8c31d 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -23,6 +23,7 @@
#include <public/sysctl.h>
#include <asm/numa.h>
#include <xen/nodemask.h>
+#include <xsm/xsm.h>
extern long arch_do_sysctl(
struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
@@ -48,6 +49,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
{
case XEN_SYSCTL_readconsole:
{
+ ret = xsm_readconsole(op->u.readconsole.clear);
+ if ( ret )
+ break;
+
ret = read_console_ring(
guest_handle_cast(op->u.readconsole.buffer, char),
&op->u.readconsole.count,
@@ -59,6 +64,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
case XEN_SYSCTL_tbuf_op:
{
+ ret = xsm_tbufcontrol();
+ if ( ret )
+ break;
+
ret = tb_control(&op->u.tbuf_op);
if ( copy_to_guest(u_sysctl, op, 1) )
ret = -EFAULT;
@@ -67,6 +76,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
case XEN_SYSCTL_sched_id:
{
+ ret = xsm_sched_id();
+ if ( ret )
+ break;
+
op->u.sched_id.sched_id = sched_id();
if ( copy_to_guest(u_sysctl, op, 1) )
ret = -EFAULT;
@@ -90,6 +103,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
if ( num_domains == op->u.getdomaininfolist.max_domains )
break;
+ ret = xsm_getdomaininfo(d);
+ if ( ret )
+ continue;
+
getdomaininfo(d, &info);
if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
@@ -117,6 +134,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
#ifdef PERF_COUNTERS
case XEN_SYSCTL_perfc_op:
{
+ ret = xsm_perfcontrol();
+ if ( ret )
+ break;
+
ret = perfc_control(&op->u.perfc_op);
if ( copy_to_guest(u_sysctl, op, 1) )
ret = -EFAULT;
diff --git a/xen/common/xenoprof.c b/xen/common/xenoprof.c
index e25ad7bb30..fee2a6556b 100644
--- a/xen/common/xenoprof.c
+++ b/xen/common/xenoprof.c
@@ -14,6 +14,7 @@
#include <xen/sched.h>
#include <public/xenoprof.h>
#include <xen/paging.h>
+#include <xsm/xsm.h>
/* Limit amount of pages used for shared buffer (per domain) */
#define MAX_OPROF_SHARED_PAGES 32
@@ -634,6 +635,10 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
return -EPERM;
}
+ ret = xsm_profile(current->domain, op);
+ if ( ret )
+ return ret;
+
spin_lock(&xenoprof_lock);
switch ( op )
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index de351265db..1d88fc8078 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -32,6 +32,7 @@
#include <asm/debugger.h>
#include <asm/io.h>
#include <asm/div64.h>
+#include <xsm/xsm.h>
/* console: comma-separated list of console outputs. */
static char opt_console[30] = OPT_CONSOLE_STR;
@@ -358,6 +359,10 @@ long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
return -EPERM;
#endif
+ rc = xsm_console_io(current->domain, cmd);
+ if ( rc )
+ return rc;
+
switch ( cmd )
{
case CONSOLEIO_write:
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index e686ccb99c..0017c3fa5d 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -80,6 +80,7 @@
#define __HYPERVISOR_sysctl 35
#define __HYPERVISOR_domctl 36
#define __HYPERVISOR_kexec_op 37
+#define __HYPERVISOR_xsm_op 38
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h
index 3ce04ded05..3fc9b3ee4f 100644
--- a/xen/include/xen/hypercall.h
+++ b/xen/include/xen/hypercall.h
@@ -15,6 +15,7 @@
#include <public/acm_ops.h>
#include <public/event_channel.h>
#include <asm/hypercall.h>
+#include <xsm/xsm.h>
extern long
do_ni_hypercall(
@@ -125,4 +126,8 @@ compat_memory_op(
#endif
+extern long
+do_xsm_op(
+ XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
+
#endif /* __XEN_HYPERCALL_H__ */
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
new file mode 100644
index 0000000000..3a6cbde29e
--- /dev/null
+++ b/xen/include/xsm/xsm.h
@@ -0,0 +1,537 @@
+/*
+ * This file contains the XSM hook definitions for Xen.
+ *
+ * This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ * Author: George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ * Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ * 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 __XSM_H__
+#define __XSM_H__
+
+#include <xen/sched.h>
+#include <xen/multiboot.h>
+
+typedef void xsm_op_t;
+DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
+
+extern long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op);
+
+#ifdef XSM_ENABLE
+ #define xsm_call(fn) xsm_ops->fn
+#else
+ #define xsm_call(fn) 0
+#endif
+
+/* policy magic number (defined by XSM_MAGIC) */
+typedef u32 xsm_magic_t;
+#ifndef XSM_MAGIC
+#define XSM_MAGIC 0x00000000
+#endif
+
+#ifdef XSM_ENABLE
+
+extern char *policy_buffer;
+extern u32 policy_size;
+
+typedef int (*xsm_initcall_t)(void);
+
+extern xsm_initcall_t __xsm_initcall_start[], __xsm_initcall_end[];
+
+#define xsm_initcall(fn) \
+ static xsm_initcall_t __initcall_##fn \
+ __attribute_used__ __attribute__((__section__(".xsm_initcall.init"))) = fn
+
+struct xsm_operations {
+ void (*security_domaininfo) (struct domain *d,
+ struct xen_domctl_getdomaininfo *info);
+ int (*setvcpucontext) (struct domain *d);
+ int (*pausedomain) (struct domain *d);
+ int (*unpausedomain) (struct domain *d);
+ int (*resumedomain) (struct domain *d);
+ int (*domain_create) (struct domain *d, u32 ssidref);
+ int (*max_vcpus) (struct domain *d);
+ int (*destroydomain) (struct domain *d);
+ int (*vcpuaffinity) (int cmd, struct domain *d);
+ int (*scheduler) (struct domain *d);
+ int (*getdomaininfo) (struct domain *d);
+ int (*getvcpucontext) (struct domain *d);
+ int (*getvcpuinfo) (struct domain *d);
+ int (*domain_settime) (struct domain *d);
+ int (*tbufcontrol) (void);
+ int (*readconsole) (uint32_t clear);
+ int (*sched_id) (void);
+ int (*setdomainmaxmem) (struct domain *d);
+ int (*setdomainhandle) (struct domain *d);
+ int (*setdebugging) (struct domain *d);
+ int (*irq_permission) (struct domain *d, uint8_t pirq, uint8_t access);
+ int (*iomem_permission) (struct domain *d, unsigned long mfn,
+ uint8_t access);
+ int (*perfcontrol) (void);
+
+ int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
+ int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
+ struct domain *d2, struct evtchn *chn2);
+ void (*evtchn_close_post) (struct evtchn *chn);
+ int (*evtchn_send) (struct domain *d, struct evtchn *chn);
+ int (*evtchn_status) (struct domain *d, struct evtchn *chn);
+ int (*evtchn_reset) (struct domain *d1, struct domain *d2);
+
+ int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t flags);
+ int (*grant_unmapref) (struct domain *d1, struct domain *d2);
+ int (*grant_setup) (struct domain *d1, struct domain *d2);
+ int (*grant_transfer) (struct domain *d1, struct domain *d2);
+ int (*grant_copy) (struct domain *d1, struct domain *d2);
+ int (*grant_query_size) (struct domain *d1, struct domain *d2);
+
+ int (*alloc_security_domain) (struct domain *d);
+ void (*free_security_domain) (struct domain *d);
+ int (*alloc_security_evtchn) (struct evtchn *chn);
+ void (*free_security_evtchn) (struct evtchn *chn);
+
+ int (*translate_gpfn_list) (struct domain *d, unsigned long mfn);
+ int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2);
+ int (*memory_stat_reservation) (struct domain *d1, struct domain *d2);
+ int (*memory_pin_page) (struct domain *d, struct page_info *page);
+ int (*update_va_mapping) (struct domain *d, l1_pgentry_t pte);
+
+ int (*console_io) (struct domain *d, int cmd);
+
+ int (*profile) (struct domain *d, int op);
+
+ int (*kexec) (void);
+ int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
+
+ long (*__do_xsm_op) (XEN_GUEST_HANDLE(xsm_op_t) op);
+ void (*complete_init) (struct domain *d);
+
+#ifdef CONFIG_X86
+ int (*shadow_control) (struct domain *d, uint32_t op);
+ int (*ioport_permission) (struct domain *d, uint32_t ioport,
+ uint8_t access);
+ int (*getpageframeinfo) (struct page_info *page);
+ int (*getmemlist) (struct domain *d);
+ int (*hypercall_init) (struct domain *d);
+ int (*hvmcontext) (struct domain *d, uint32_t op);
+ int (*address_size) (struct domain *d, uint32_t op);
+ int (*hvm_param) (struct domain *d, unsigned long op);
+ int (*hvm_set_pci_intx_level) (struct domain *d);
+ int (*hvm_set_isa_irq_level) (struct domain *d);
+ int (*hvm_set_pci_link_route) (struct domain *d);
+ int (*apic) (struct domain *d, int cmd);
+ int (*assign_vector) (struct domain *d, uint32_t pirq);
+ int (*xen_settime) (void);
+ int (*memtype) (uint32_t access);
+ int (*microcode) (void);
+ int (*physinfo) (void);
+ int (*platform_quirk) (uint32_t);
+ int (*machine_memory_map) (void);
+ int (*domain_memory_map) (struct domain *d);
+ int (*mmu_normal_update) (struct domain *d, intpte_t fpte);
+ int (*mmu_machphys_update) (struct domain *d, unsigned long mfn);
+ int (*add_to_physmap) (struct domain *d1, struct domain *d2);
+#endif
+};
+
+#endif
+
+extern struct xsm_operations *xsm_ops;
+
+static inline void xsm_security_domaininfo (struct domain *d,
+ struct xen_domctl_getdomaininfo *info)
+{
+ xsm_call(security_domaininfo(d, info));
+}
+
+static inline int xsm_setvcpucontext(struct domain *d)
+{
+ return xsm_call(setvcpucontext(d));
+}
+
+static inline int xsm_pausedomain (struct domain *d)
+{
+ return xsm_call(pausedomain(d));
+}
+
+static inline int xsm_unpausedomain (struct domain *d)
+{
+ return xsm_call(unpausedomain(d));
+}
+
+static inline int xsm_resumedomain (struct domain *d)
+{
+ return xsm_call(resumedomain(d));
+}
+
+static inline int xsm_domain_create (struct domain *d, u32 ssidref)
+{
+ return xsm_call(domain_create(d, ssidref));
+}
+
+static inline int xsm_max_vcpus(struct domain *d)
+{
+ return xsm_call(max_vcpus(d));
+}
+
+static inline int xsm_destroydomain (struct domain *d)
+{
+ return xsm_call(destroydomain(d));
+}
+
+static inline int xsm_vcpuaffinity (int cmd, struct domain *d)
+{
+ return xsm_call(vcpuaffinity(cmd, d));
+}
+
+static inline int xsm_scheduler (struct domain *d)
+{
+ return xsm_call(scheduler(d));
+}
+
+static inline int xsm_getdomaininfo (struct domain *d)
+{
+ return xsm_call(getdomaininfo(d));
+}
+
+static inline int xsm_getvcpucontext (struct domain *d)
+{
+ return xsm_call(getvcpucontext(d));
+}
+
+static inline int xsm_getvcpuinfo (struct domain *d)
+{
+ return xsm_call(getvcpuinfo(d));
+}
+
+static inline int xsm_domain_settime (struct domain *d)
+{
+ return xsm_call(domain_settime(d));
+}
+
+static inline int xsm_tbufcontrol (void)
+{
+ return xsm_call(tbufcontrol());
+}
+
+static inline int xsm_readconsole (uint32_t clear)
+{
+ return xsm_call(readconsole(clear));
+}
+
+static inline int xsm_sched_id (void)
+{
+ return xsm_call(sched_id());
+}
+
+static inline int xsm_setdomainmaxmem (struct domain *d)
+{
+ return xsm_call(setdomainmaxmem(d));
+}
+
+static inline int xsm_setdomainhandle (struct domain *d)
+{
+ return xsm_call(setdomainhandle(d));
+}
+
+static inline int xsm_setdebugging (struct domain *d)
+{
+ return xsm_call(setdebugging(d));
+}
+
+static inline int xsm_irq_permission (struct domain *d, uint8_t pirq,
+ uint8_t access)
+{
+ return xsm_call(irq_permission(d, pirq, access));
+}
+
+static inline int xsm_iomem_permission (struct domain *d, unsigned long mfn,
+ uint8_t access)
+{
+ return xsm_call(iomem_permission(d, mfn, access));
+}
+
+static inline int xsm_perfcontrol (void)
+{
+ return xsm_call(perfcontrol());
+}
+
+static inline int xsm_evtchn_unbound (struct domain *d1, struct evtchn *chn,
+ domid_t id2)
+{
+ return xsm_call(evtchn_unbound(d1, chn, id2));
+}
+
+static inline int xsm_evtchn_interdomain (struct domain *d1,
+ struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
+{
+ return xsm_call(evtchn_interdomain(d1, chan1, d2, chan2));
+}
+
+static inline void xsm_evtchn_close_post (struct evtchn *chn)
+{
+ xsm_call(evtchn_close_post(chn));
+}
+
+static inline int xsm_evtchn_send (struct domain *d, struct evtchn *chn)
+{
+ return xsm_call(evtchn_send(d, chn));
+}
+
+static inline int xsm_evtchn_status (struct domain *d, struct evtchn *chn)
+{
+ return xsm_call(evtchn_status(d, chn));
+}
+
+static inline int xsm_evtchn_reset (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(evtchn_reset(d1, d2));
+}
+
+static inline int xsm_grant_mapref (struct domain *d1, struct domain *d2,
+ uint32_t flags)
+{
+ return xsm_call(grant_mapref(d1, d2, flags));
+}
+
+static inline int xsm_grant_unmapref (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(grant_unmapref(d1, d2));
+}
+
+static inline int xsm_grant_setup (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(grant_setup(d1, d2));
+}
+
+static inline int xsm_grant_transfer (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(grant_transfer(d1, d2));
+}
+
+static inline int xsm_grant_copy (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(grant_copy(d1, d2));
+}
+
+static inline int xsm_grant_query_size (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(grant_query_size(d1, d2));
+}
+
+static inline int xsm_alloc_security_domain (struct domain *d)
+{
+ return xsm_call(alloc_security_domain(d));
+}
+
+static inline void xsm_free_security_domain (struct domain *d)
+{
+ xsm_call(free_security_domain(d));
+}
+
+static inline int xsm_alloc_security_evtchn (struct evtchn *chn)
+{
+ return xsm_call(alloc_security_evtchn(chn));
+}
+
+static inline void xsm_free_security_evtchn (struct evtchn *chn)
+{
+ xsm_call(free_security_evtchn(chn));
+}
+
+static inline int xsm_translate_gpfn_list (struct domain *d, unsigned long mfn)
+{
+ return xsm_call(translate_gpfn_list(d, mfn));
+}
+
+static inline int xsm_memory_adjust_reservation (struct domain *d1, struct
+ domain *d2)
+{
+ return xsm_call(memory_adjust_reservation(d1, d2));
+}
+
+static inline int xsm_memory_stat_reservation (struct domain *d1,
+ struct domain *d2)
+{
+ return xsm_call(memory_stat_reservation(d1, d2));
+}
+
+static inline int xsm_memory_pin_page(struct domain *d, struct page_info *page)
+{
+ return xsm_call(memory_pin_page(d, page));
+}
+
+static inline int xsm_update_va_mapping(struct domain *d, l1_pgentry_t pte)
+{
+ return xsm_call(update_va_mapping(d, pte));
+}
+
+static inline int xsm_console_io (struct domain *d, int cmd)
+{
+ return xsm_call(console_io(d, cmd));
+}
+
+static inline int xsm_profile (struct domain *d, int op)
+{
+ return xsm_call(profile(d, op));
+}
+
+static inline int xsm_kexec (void)
+{
+ return xsm_call(kexec());
+}
+
+static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2)
+{
+ return xsm_call(schedop_shutdown(d1, d2));
+}
+
+static inline long __do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
+{
+ return xsm_call(__do_xsm_op(op));
+}
+
+static inline void xsm_complete_init (struct domain *d)
+{
+ xsm_call(complete_init(d));
+}
+
+#ifdef XSM_ENABLE
+extern int xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+ unsigned long initial_images_start);
+extern int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+ unsigned long initial_images_start);
+extern int register_xsm(struct xsm_operations *ops);
+extern int unregister_xsm(struct xsm_operations *ops);
+#else
+static inline int xsm_init (unsigned int *initrdidx,
+ const multiboot_info_t *mbi, unsigned long initial_images_start)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_X86
+static inline int xsm_shadow_control (struct domain *d, uint32_t op)
+{
+ return xsm_call(shadow_control(d, op));
+}
+
+static inline int xsm_ioport_permission (struct domain *d, uint32_t ioport,
+ uint8_t access)
+{
+ return xsm_call(ioport_permission(d, ioport, access));
+}
+
+static inline int xsm_getpageframeinfo (struct page_info *page)
+{
+ return xsm_call(getpageframeinfo(page));
+}
+
+static inline int xsm_getmemlist (struct domain *d)
+{
+ return xsm_call(getmemlist(d));
+}
+
+static inline int xsm_hypercall_init (struct domain *d)
+{
+ return xsm_call(hypercall_init(d));
+}
+
+static inline int xsm_hvmcontext (struct domain *d, uint32_t cmd)
+{
+ return xsm_call(hvmcontext(d, cmd));
+}
+
+static inline int xsm_address_size (struct domain *d, uint32_t cmd)
+{
+ return xsm_call(address_size(d, cmd));
+}
+
+static inline int xsm_hvm_param (struct domain *d, unsigned long op)
+{
+ return xsm_call(hvm_param(d, op));
+}
+
+static inline int xsm_hvm_set_pci_intx_level (struct domain *d)
+{
+ return xsm_call(hvm_set_pci_intx_level(d));
+}
+
+static inline int xsm_hvm_set_isa_irq_level (struct domain *d)
+{
+ return xsm_call(hvm_set_isa_irq_level(d));
+}
+
+static inline int xsm_hvm_set_pci_link_route (struct domain *d)
+{
+ return xsm_call(hvm_set_pci_link_route(d));
+}
+
+static inline int xsm_apic (struct domain *d, int cmd)
+{
+ return xsm_call(apic(d, cmd));
+}
+
+static inline int xsm_assign_vector (struct domain *d, uint32_t pirq)
+{
+ return xsm_call(assign_vector(d, pirq));
+}
+
+static inline int xsm_xen_settime (void)
+{
+ return xsm_call(xen_settime());
+}
+
+static inline int xsm_memtype (uint32_t access)
+{
+ return xsm_call(memtype(access));
+}
+
+static inline int xsm_microcode (void)
+{
+ return xsm_call(microcode());
+}
+
+static inline int xsm_physinfo (void)
+{
+ return xsm_call(physinfo());
+}
+
+static inline int xsm_platform_quirk (uint32_t quirk)
+{
+ return xsm_call(platform_quirk(quirk));
+}
+
+static inline int xsm_machine_memory_map(void)
+{
+ return xsm_call(machine_memory_map());
+}
+
+static inline int xsm_domain_memory_map(struct domain *d)
+{
+ return xsm_call(domain_memory_map(d));
+}
+
+static inline int xsm_mmu_normal_update (struct domain *d, intpte_t fpte)
+{
+ return xsm_call(mmu_normal_update(d, fpte));
+}
+
+static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn)
+{
+ return xsm_call(mmu_machphys_update(d, mfn));
+}
+
+static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2)
+{
+ return xsm_call(add_to_physmap(d1, d2));
+}
+#endif /* CONFIG_X86 */
+
+#endif /* __XSM_H */
diff --git a/xen/xsm/Makefile b/xen/xsm/Makefile
new file mode 100644
index 0000000000..252459cc00
--- /dev/null
+++ b/xen/xsm/Makefile
@@ -0,0 +1,5 @@
+obj-y += xsm_core.o
+obj-y += xsm_policy.o
+ifeq ($(XSM_ENABLE),y)
+obj-y += dummy.o
+endif
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
new file mode 100644
index 0000000000..c572f67799
--- /dev/null
+++ b/xen/xsm/dummy.c
@@ -0,0 +1,488 @@
+/*
+ * This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ * Author: George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ * Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ * 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 <xen/sched.h>
+#include <xsm/xsm.h>
+
+static void dummy_security_domaininfo(struct domain *d,
+ struct xen_domctl_getdomaininfo *info)
+{
+ return;
+}
+
+static int dummy_setvcpucontext(struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_pausedomain (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_unpausedomain (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_resumedomain (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_domain_create(struct domain *d, u32 ssidref)
+{
+ return 0;
+}
+
+static int dummy_max_vcpus(struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_destroydomain (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_vcpuaffinity (int cmd, struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_scheduler (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_getdomaininfo (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_getvcpucontext (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_getvcpuinfo (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_domain_settime (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_tbufcontrol (void)
+{
+ return 0;
+}
+
+static int dummy_readconsole (uint32_t clear)
+{
+ return 0;
+}
+
+static int dummy_sched_id (void)
+{
+ return 0;
+}
+
+static int dummy_setdomainmaxmem (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_setdomainhandle (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_setdebugging (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_irq_permission (struct domain *d, uint8_t pirq, uint8_t access)
+{
+ return 0;
+}
+
+static int dummy_iomem_permission (struct domain *d, unsigned long mfn,
+ uint8_t access)
+{
+ return 0;
+}
+
+static int dummy_perfcontrol (void)
+{
+ return 0;
+}
+
+static int dummy_alloc_security_domain (struct domain *d)
+{
+ return 0;
+}
+
+static void dummy_free_security_domain (struct domain *d)
+{
+ return;
+}
+
+static int dummy_grant_mapref (struct domain *d1, struct domain *d2,
+ uint32_t flags)
+{
+ return 0;
+}
+
+static int dummy_grant_unmapref (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_grant_setup (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_grant_transfer (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_grant_copy (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_grant_query_size (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_translate_gpfn_list (struct domain *d, unsigned long mfn)
+{
+ return 0;
+}
+
+static int dummy_memory_adjust_reservation (struct domain *d1,
+ struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_memory_stat_reservation (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_update_va_mapping (struct domain *d, l1_pgentry_t pte)
+{
+ return 0;
+}
+
+static int dummy_console_io (struct domain *d, int cmd)
+{
+ return 0;
+}
+
+static int dummy_profile (struct domain *d, int op)
+{
+ return 0;
+}
+
+static int dummy_kexec (void)
+{
+ return 0;
+}
+
+static int dummy_schedop_shutdown (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_memory_pin_page(struct domain *d, struct page_info *page)
+{
+ return 0;
+}
+
+static int dummy_evtchn_unbound (struct domain *d, struct evtchn *chn,
+ domid_t id2)
+{
+ return 0;
+}
+
+static int dummy_evtchn_interdomain (struct domain *d1, struct evtchn
+ *chan1, struct domain *d2, struct evtchn *chan2)
+{
+ return 0;
+}
+
+static void dummy_evtchn_close_post (struct evtchn *chn)
+{
+ return;
+}
+
+static int dummy_evtchn_send (struct domain *d, struct evtchn *chn)
+{
+ return 0;
+}
+
+static int dummy_evtchn_status (struct domain *d, struct evtchn *chn)
+{
+ return 0;
+}
+
+static int dummy_evtchn_reset (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
+static int dummy_alloc_security_evtchn (struct evtchn *chn)
+{
+ return 0;
+}
+
+static void dummy_free_security_evtchn (struct evtchn *chn)
+{
+ return;
+}
+
+static void dummy_complete_init (struct domain *d)
+{
+ return;
+}
+
+static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op)
+{
+ return -ENOSYS;
+}
+
+#ifdef CONFIG_X86
+static int dummy_shadow_control (struct domain *d, uint32_t op)
+{
+ return 0;
+}
+
+static int dummy_ioport_permission (struct domain *d, uint32_t ioport,
+ uint8_t access)
+{
+ return 0;
+}
+
+static int dummy_getpageframeinfo (struct page_info *page)
+{
+ return 0;
+}
+
+static int dummy_getmemlist (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_hypercall_init (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_hvmcontext (struct domain *d, uint32_t cmd)
+{
+ return 0;
+}
+
+static int dummy_address_size (struct domain *d, uint32_t cmd)
+{
+ return 0;
+}
+
+static int dummy_hvm_param (struct domain *d, unsigned long op)
+{
+ return 0;
+}
+
+static int dummy_hvm_set_pci_intx_level (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_hvm_set_isa_irq_level (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_hvm_set_pci_link_route (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_apic (struct domain *d, int cmd)
+{
+ return 0;
+}
+
+static int dummy_assign_vector (struct domain *d, uint32_t pirq)
+{
+ return 0;
+}
+
+static int dummy_xen_settime (void)
+{
+ return 0;
+}
+
+static int dummy_memtype (uint32_t access)
+{
+ return 0;
+}
+
+static int dummy_microcode (void)
+{
+ return 0;
+}
+
+static int dummy_physinfo (void)
+{
+ return 0;
+}
+
+static int dummy_platform_quirk (uint32_t quirk)
+{
+ return 0;
+}
+
+static int dummy_machine_memory_map (void)
+{
+ return 0;
+}
+
+static int dummy_domain_memory_map (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_mmu_normal_update (struct domain *d, intpte_t fpte)
+{
+ return 0;
+}
+
+static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn)
+{
+ return 0;
+}
+
+static int dummy_add_to_physmap (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+#endif
+
+struct xsm_operations dummy_xsm_ops;
+
+#define set_to_dummy_if_null(ops, function) \
+ do { \
+ if ( !ops->function ) \
+ { \
+ ops->function = dummy_##function; \
+ dprintk(XENLOG_DEBUG, "Had to override the " #function \
+ " security operation with the dummy one.\n"); \
+ } \
+ } while (0)
+
+void xsm_fixup_ops (struct xsm_operations *ops)
+{
+ set_to_dummy_if_null(ops, security_domaininfo);
+ set_to_dummy_if_null(ops, setvcpucontext);
+ set_to_dummy_if_null(ops, pausedomain);
+ set_to_dummy_if_null(ops, unpausedomain);
+ set_to_dummy_if_null(ops, resumedomain);
+ set_to_dummy_if_null(ops, domain_create);
+ set_to_dummy_if_null(ops, max_vcpus);
+ set_to_dummy_if_null(ops, destroydomain);
+ set_to_dummy_if_null(ops, vcpuaffinity);
+ set_to_dummy_if_null(ops, scheduler);
+ set_to_dummy_if_null(ops, getdomaininfo);
+ set_to_dummy_if_null(ops, getvcpucontext);
+ set_to_dummy_if_null(ops, getvcpuinfo);
+ set_to_dummy_if_null(ops, domain_settime);
+ set_to_dummy_if_null(ops, tbufcontrol);
+ set_to_dummy_if_null(ops, readconsole);
+ set_to_dummy_if_null(ops, sched_id);
+ set_to_dummy_if_null(ops, setdomainmaxmem);
+ set_to_dummy_if_null(ops, setdomainhandle);
+ set_to_dummy_if_null(ops, setdebugging);
+ set_to_dummy_if_null(ops, irq_permission);
+ set_to_dummy_if_null(ops, iomem_permission);
+ set_to_dummy_if_null(ops, perfcontrol);
+
+ set_to_dummy_if_null(ops, evtchn_unbound);
+ set_to_dummy_if_null(ops, evtchn_interdomain);
+ set_to_dummy_if_null(ops, evtchn_close_post);
+ set_to_dummy_if_null(ops, evtchn_send);
+ set_to_dummy_if_null(ops, evtchn_status);
+ set_to_dummy_if_null(ops, evtchn_reset);
+
+ set_to_dummy_if_null(ops, grant_mapref);
+ set_to_dummy_if_null(ops, grant_unmapref);
+ set_to_dummy_if_null(ops, grant_setup);
+ set_to_dummy_if_null(ops, grant_transfer);
+ set_to_dummy_if_null(ops, grant_copy);
+ set_to_dummy_if_null(ops, grant_query_size);
+
+ set_to_dummy_if_null(ops, alloc_security_domain);
+ set_to_dummy_if_null(ops, free_security_domain);
+ set_to_dummy_if_null(ops, alloc_security_evtchn);
+ set_to_dummy_if_null(ops, free_security_evtchn);
+
+ set_to_dummy_if_null(ops, translate_gpfn_list);
+ set_to_dummy_if_null(ops, memory_adjust_reservation);
+ set_to_dummy_if_null(ops, memory_stat_reservation);
+ set_to_dummy_if_null(ops, memory_pin_page);
+ set_to_dummy_if_null(ops, update_va_mapping);
+
+ set_to_dummy_if_null(ops, console_io);
+
+ set_to_dummy_if_null(ops, profile);
+
+ set_to_dummy_if_null(ops, kexec);
+ set_to_dummy_if_null(ops, schedop_shutdown);
+
+ set_to_dummy_if_null(ops, __do_xsm_op);
+ set_to_dummy_if_null(ops, complete_init);
+
+#ifdef CONFIG_X86
+ set_to_dummy_if_null(ops, shadow_control);
+ set_to_dummy_if_null(ops, ioport_permission);
+ set_to_dummy_if_null(ops, getpageframeinfo);
+ set_to_dummy_if_null(ops, getmemlist);
+ set_to_dummy_if_null(ops, hypercall_init);
+ set_to_dummy_if_null(ops, hvmcontext);
+ set_to_dummy_if_null(ops, address_size);
+ set_to_dummy_if_null(ops, hvm_param);
+ set_to_dummy_if_null(ops, hvm_set_pci_intx_level);
+ set_to_dummy_if_null(ops, hvm_set_isa_irq_level);
+ set_to_dummy_if_null(ops, hvm_set_pci_link_route);
+ set_to_dummy_if_null(ops, apic);
+ set_to_dummy_if_null(ops, assign_vector);
+ set_to_dummy_if_null(ops, xen_settime);
+ set_to_dummy_if_null(ops, memtype);
+ set_to_dummy_if_null(ops, microcode);
+ set_to_dummy_if_null(ops, physinfo);
+ set_to_dummy_if_null(ops, platform_quirk);
+ set_to_dummy_if_null(ops, machine_memory_map);
+ set_to_dummy_if_null(ops, domain_memory_map);
+ set_to_dummy_if_null(ops, mmu_normal_update);
+ set_to_dummy_if_null(ops, mmu_machphys_update);
+ set_to_dummy_if_null(ops, add_to_physmap);
+#endif
+}
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
new file mode 100644
index 0000000000..d572f997c0
--- /dev/null
+++ b/xen/xsm/xsm_core.c
@@ -0,0 +1,118 @@
+/*
+ * This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ * Author: George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ * Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ * 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 <xen/init.h>
+#include <xen/errno.h>
+#include <xen/lib.h>
+
+#include <xsm/xsm.h>
+
+#ifdef XSM_ENABLE
+
+#define XSM_FRAMEWORK_VERSION "1.0.0"
+
+extern struct xsm_operations dummy_xsm_ops;
+extern void xsm_fixup_ops(struct xsm_operations *ops);
+
+struct xsm_operations *xsm_ops;
+
+static inline int verify(struct xsm_operations *ops)
+{
+ /* verify the security_operations structure exists */
+ if ( !ops )
+ return -EINVAL;
+ xsm_fixup_ops(ops);
+ return 0;
+}
+
+static void __init do_xsm_initcalls(void)
+{
+ xsm_initcall_t *call;
+ call = __xsm_initcall_start;
+ while ( call < __xsm_initcall_end )
+ {
+ (*call) ();
+ call++;
+ }
+}
+
+int __init xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+ unsigned long initial_images_start)
+{
+ int ret = 0;
+
+ printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
+
+ if ( XSM_MAGIC )
+ {
+ ret = xsm_policy_init(initrdidx, mbi, initial_images_start);
+ if ( ret )
+ {
+ printk("%s: Error initializing policy.\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ }
+
+ if ( verify(&dummy_xsm_ops) )
+ {
+ printk("%s could not verify "
+ "dummy_xsm_ops structure.\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ xsm_ops = &dummy_xsm_ops;
+ do_xsm_initcalls();
+
+ return 0;
+}
+
+int register_xsm(struct xsm_operations *ops)
+{
+ if ( verify(ops) )
+ {
+ printk("%s could not verify "
+ "security_operations structure.\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if ( xsm_ops != &dummy_xsm_ops )
+ return -EAGAIN;
+
+ xsm_ops = ops;
+
+ return 0;
+}
+
+
+int unregister_xsm(struct xsm_operations *ops)
+{
+ if ( ops != xsm_ops )
+ {
+ printk("%s: trying to unregister "
+ "a security_opts structure that is not "
+ "registered, failing.\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ xsm_ops = &dummy_xsm_ops;
+
+ return 0;
+}
+
+#endif
+
+long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
+{
+ return __do_xsm_op(op);
+}
+
+
diff --git a/xen/xsm/xsm_policy.c b/xen/xsm/xsm_policy.c
new file mode 100644
index 0000000000..6da6e3164e
--- /dev/null
+++ b/xen/xsm/xsm_policy.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer, <sailer@watson.ibm.com>
+ * Stefan Berger, <stefanb@watson.ibm.com>
+ *
+ * Contributors:
+ * Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ * George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ * 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.
+ *
+ *
+ * This file contains the XSM policy init functions for Xen.
+ * This file is based on the ACM functions of the same name.
+ *
+ */
+
+#include <xsm/xsm.h>
+#include <xen/multiboot.h>
+
+char *policy_buffer = NULL;
+u32 policy_size = 0;
+
+int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+ unsigned long initial_images_start)
+{
+ int i;
+ module_t *mod = (module_t *)__va(mbi->mods_addr);
+ int rc = 0;
+ u32 *_policy_start;
+ unsigned long start, _policy_len;
+
+ /*
+ * Try all modules and see whichever could be the binary policy.
+ * Adjust the initrdidx if module[1] is the binary policy.
+ */
+ for ( i = mbi->mods_count-1; i >= 1; i-- )
+ {
+ start = initial_images_start + (mod[i].mod_start-mod[0].mod_start);
+#if defined(__i386__)
+ _policy_start = (u32 *)start;
+#elif defined(__x86_64__)
+ _policy_start = maddr_to_virt(start);
+#endif
+ _policy_len = mod[i].mod_end - mod[i].mod_start;
+
+ if ( (xsm_magic_t)(*_policy_start) == XSM_MAGIC )
+ {
+ policy_buffer = (char *)_policy_start;
+ policy_size = _policy_len;
+
+ printk("Policy len 0x%lx, start at %p.\n",
+ _policy_len,_policy_start);
+
+ if ( i == 1 )
+ *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
+ break;
+
+ }
+ }
+
+ return rc;
+}