[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Xen Security Modules: ACM.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1188556909 -3600
# Node ID fa4d44c9d9f668867f6cb578155433678f6c5a93
# Parent  993655d24b5502c56e27c9f52498934b2d528ff9
Xen Security Modules: ACM.
Signed-off-by: George Coker <gscoker@xxxxxxxxxxxxxx>
---
 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/common/acm_ops.c                            |  212 -----
 tools/libxc/xc_acm.c                            |    2 
 tools/python/xen/util/xsm/xsm.py                |    9 
 xen/Makefile                                    |    3 
 xen/Rules.mk                                    |    3 
 xen/arch/x86/setup.c                            |   42 -
 xen/arch/x86/x86_32/entry.S                     |    6 
 xen/arch/x86/x86_64/compat/entry.S              |    4 
 xen/arch/x86/x86_64/entry.S                     |    5 
 xen/common/Makefile                             |    1 
 xen/common/domain.c                             |   11 
 xen/common/domctl.c                             |    6 
 xen/common/event_channel.c                      |    7 
 xen/common/grant_table.c                        |    7 
 xen/include/acm/acm_hooks.h                     |    4 
 xen/include/public/acm.h                        |    2 
 xen/include/public/xen.h                        |    3 
 xen/include/xen/hypercall.h                     |   13 
 xen/xsm/Makefile                                |    1 
 xen/xsm/acm/Makefile                            |    7 
 xen/xsm/acm/acm_chinesewall_hooks.c             |  724 +++++++++++++++++++
 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                     |   72 +
 flask/loadpolicy/flask-loadpolicy               |    0 
 34 files changed, 3328 insertions(+), 3321 deletions(-)

diff -r 993655d24b55 -r fa4d44c9d9f6 tools/flask/loadpolicy/flask-loadpolicy
Binary file tools/flask/loadpolicy/flask-loadpolicy has changed
diff -r 993655d24b55 -r fa4d44c9d9f6 tools/libxc/xc_acm.c
--- a/tools/libxc/xc_acm.c      Fri Aug 31 11:37:20 2007 +0100
+++ b/tools/libxc/xc_acm.c      Fri Aug 31 11:41:49 2007 +0100
@@ -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 993655d24b55 -r fa4d44c9d9f6 tools/python/xen/util/xsm/xsm.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/util/xsm/xsm.py  Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,9 @@
+XEN_SECURITY_MODULE = "flask"
+from xsm_core import *
+
+import xen.util.xsm.flask.flask as xsm_module
+
+xsm_init(xsm_module)
+from xen.util.xsm.flask.flask import *
+del xsm_module
+
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/Makefile
--- a/xen/Makefile      Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/Makefile      Fri Aug 31 11:41:49 2007 +0100
@@ -55,7 +55,6 @@ _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
@@ -123,7 +122,7 @@ build-headers:
 build-headers:
        $(MAKE) -C include/public/foreign
 
-SUBDIRS = xsm 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 993655d24b55 -r fa4d44c9d9f6 xen/Rules.mk
--- a/xen/Rules.mk      Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/Rules.mk      Fri Aug 31 11:41:49 2007 +0100
@@ -53,7 +53,6 @@ ALL_OBJS-y               += $(BASEDIR)/c
 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__
@@ -62,7 +61,7 @@ CFLAGS-$(FLASK_DEVELOP)   += -DFLASK_DEV
 CFLAGS-$(FLASK_DEVELOP)   += -DFLASK_DEVELOP
 CFLAGS-$(FLASK_BOOTPARAM) += -DFLASK_BOOTPARAM
 CFLAGS-$(FLASK_AVC_STATS) += -DFLASK_AVC_STATS
-CFLAGS-$(ACM_SECURITY)  += -DACM_SECURITY
+CFLAGS-$(ACM_SECURITY)    += -DACM_SECURITY -DXSM_MAGIC=0xbcde0100
 CFLAGS-$(verbose)       += -DVERBOSE
 CFLAGS-$(crash_debug)   += -DCRASH_DEBUG
 CFLAGS-$(perfc)         += -DPERF_COUNTERS
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/acm/Makefile
--- a/xen/acm/Makefile  Fri Aug 31 11:37:20 2007 +0100
+++ /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 993655d24b55 -r fa4d44c9d9f6 xen/acm/acm_chinesewall_hooks.c
--- a/xen/acm/acm_chinesewall_hooks.c   Fri Aug 31 11:37:20 2007 +0100
+++ /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 993655d24b55 -r fa4d44c9d9f6 xen/acm/acm_core.c
--- a/xen/acm/acm_core.c        Fri Aug 31 11:37:20 2007 +0100
+++ /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 993655d24b55 -r fa4d44c9d9f6 xen/acm/acm_null_hooks.c
--- a/xen/acm/acm_null_hooks.c  Fri Aug 31 11:37:20 2007 +0100
+++ /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 993655d24b55 -r fa4d44c9d9f6 xen/acm/acm_policy.c
--- a/xen/acm/acm_policy.c      Fri Aug 31 11:37:20 2007 +0100
+++ /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 993655d24b55 -r fa4d44c9d9f6 xen/acm/acm_simple_type_enforcement_hooks.c
--- a/xen/acm/acm_simple_type_enforcement_hooks.c       Fri Aug 31 11:37:20 
2007 +0100
+++ /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 993655d24b55 -r fa4d44c9d9f6 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/arch/x86/setup.c      Fri Aug 31 11:41:49 2007 +0100
@@ -220,40 +220,6 @@ static void __init percpu_init_areas(voi
 #endif
 }
 
-/* Fetch acm policy module from multiboot modules. */
-static void __init extract_acm_policy(
-    multiboot_info_t *mbi,
-    unsigned int *initrdidx,
-    char **_policy_start,
-    unsigned long *_policy_len)
-{
-    int i;
-    module_t *mod = (module_t *)__va(mbi->mods_addr);
-    unsigned long start, policy_len;
-    char *policy_start;
-
-    /*
-     * 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);
-        policy_start = maddr_to_bootstrap_virt(start);
-        policy_len   = mod[i].mod_end - mod[i].mod_start;
-        if ( acm_is_policy(policy_start, policy_len) )
-        {
-            printk("Policy len  0x%lx, start at %p - module %d.\n",
-                   policy_len, policy_start, i);
-            *_policy_start = policy_start;
-            *_policy_len = policy_len;
-            if ( i == 1 )
-                *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
-            break;
-        }
-    }
-}
-
 static void __init init_idle_domain(void)
 {
     struct domain *idle_domain;
@@ -448,8 +414,6 @@ void __init __start_xen(unsigned long mb
     char *cmdline, *kextra;
     unsigned long _initrd_start = 0, _initrd_len = 0;
     unsigned int initrdidx = 1;
-    char *_policy_start = NULL;
-    unsigned long _policy_len = 0;
     multiboot_info_t *mbi = __va(mbi_p);
     module_t *mod = (module_t *)__va(mbi->mods_addr);
     unsigned long nr_pages, modules_length;
@@ -1032,12 +996,6 @@ void __init __start_xen(unsigned long mb
     if ( opt_watchdog ) 
         watchdog_enable();
 
-    /* Extract policy from multiboot.  */
-    extract_acm_policy(mbi, &initrdidx, &_policy_start, &_policy_len);
-
-    /* initialize access control security module */
-    acm_init(_policy_start, _policy_len);
-
     /* Create initial domain 0. */
     dom0 = domain_create(0, 0, DOM0_SSIDREF);
     if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/arch/x86/x86_32/entry.S       Fri Aug 31 11:41:49 2007 +0100
@@ -665,7 +665,7 @@ ENTRY(hypercall_table)
         .long do_vcpu_op
         .long do_ni_hypercall       /* 25 */
         .long do_mmuext_op
-        .long do_acm_op
+        .long do_xsm_op
         .long do_nmi_op
         .long do_sched_op
         .long do_callback_op        /* 30 */
@@ -676,7 +676,6 @@ 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
@@ -709,7 +708,7 @@ ENTRY(hypercall_args_table)
         .byte 3 /* do_vcpu_op           */
         .byte 0 /* do_ni_hypercall      */  /* 25 */
         .byte 4 /* do_mmuext_op         */
-        .byte 1 /* do_acm_op            */
+        .byte 1 /* do_xsm_op            */
         .byte 2 /* do_nmi_op            */
         .byte 2 /* do_sched_op          */
         .byte 2 /* do_callback_op       */  /* 30 */
@@ -720,7 +719,6 @@ 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 -r 993655d24b55 -r fa4d44c9d9f6 xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S        Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/arch/x86/x86_64/compat/entry.S        Fri Aug 31 11:41:49 2007 +0100
@@ -331,7 +331,7 @@ ENTRY(compat_hypercall_table)
         .quad compat_vcpu_op
         .quad compat_ni_hypercall       /* 25 */
         .quad compat_mmuext_op
-        .quad do_acm_op
+        .quad do_xsm_op
         .quad compat_nmi_op
         .quad compat_sched_op
         .quad compat_callback_op        /* 30 */
@@ -374,7 +374,7 @@ ENTRY(compat_hypercall_args_table)
         .byte 3 /* compat_vcpu_op           */
         .byte 0 /* compat_ni_hypercall      */  /* 25 */
         .byte 4 /* compat_mmuext_op         */
-        .byte 1 /* do_acm_op                */
+        .byte 1 /* do_xsm_op                */
         .byte 2 /* compat_nmi_op            */
         .byte 2 /* compat_sched_op          */
         .byte 2 /* compat_callback_op       */  /* 30 */
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/arch/x86/x86_64/entry.S       Fri Aug 31 11:41:49 2007 +0100
@@ -601,7 +601,7 @@ ENTRY(hypercall_table)
         .quad do_vcpu_op
         .quad do_set_segment_base   /* 25 */
         .quad do_mmuext_op
-        .quad do_acm_op
+        .quad do_xsm_op
         .quad do_nmi_op
         .quad do_sched_op
         .quad do_callback_op        /* 30 */
@@ -612,7 +612,6 @@ 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
@@ -645,7 +644,7 @@ ENTRY(hypercall_args_table)
         .byte 3 /* do_vcpu_op           */
         .byte 2 /* do_set_segment_base  */  /* 25 */
         .byte 4 /* do_mmuext_op         */
-        .byte 1 /* do_acm_op            */
+        .byte 1 /* do_xsm_op            */
         .byte 2 /* do_nmi_op            */
         .byte 2 /* do_sched_op          */
         .byte 2 /* do_callback_op       */  /* 30 */
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/common/Makefile
--- a/xen/common/Makefile       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/common/Makefile       Fri Aug 31 11:41:49 2007 +0100
@@ -1,4 +1,3 @@ obj-y += acm_ops.o
-obj-y += acm_ops.o
 obj-y += bitmap.o
 obj-y += domctl.o
 obj-y += domain.o
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/common/acm_ops.c
--- a/xen/common/acm_ops.c      Fri Aug 31 11:37:20 2007 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-/******************************************************************************
- * acm_ops.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.
- *
- * Process acm command requests from guest OS.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <public/acm.h>
-#include <public/acm_ops.h>
-#include <xen/sched.h>
-#include <xen/event.h>
-#include <xen/trace.h>
-#include <xen/console.h>
-#include <xen/guest_access.h>
-#include <acm/acm_hooks.h>
-
-#ifndef ACM_SECURITY
-
-long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
-{
-    return -ENOSYS;
-}
-
-#else
-
-int acm_authorize_acm_ops(struct domain *d)
-{
-    /* currently, policy management functions are restricted to privileged 
domains */
-    return (IS_PRIV(d) ? 0 : -EPERM);
-}
-
-
-long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
-{
-    long rc = -EFAULT;
-    struct xen_acmctl curop, *op = &curop;
-
-    if (acm_authorize_acm_ops(current->domain))
-        return -EPERM;
-
-    if ( copy_from_guest(op, u_acmctl, 1) )
-        return -EFAULT;
-
-    if (op->interface_version != ACM_INTERFACE_VERSION)
-        return -EACCES;
-
-    switch ( op->cmd )
-    {
-
-    case ACMOP_setpolicy: {
-        rc = acm_set_policy(op->u.setpolicy.pushcache,
-                            op->u.setpolicy.pushcache_size);
-        break;
-    }
-
-    case ACMOP_getpolicy: {
-        rc = acm_get_policy(op->u.getpolicy.pullcache,
-                            op->u.getpolicy.pullcache_size);
-        break;
-    }
-
-    case ACMOP_dumpstats: {
-        rc = acm_dump_statistics(op->u.dumpstats.pullcache,
-                                 op->u.dumpstats.pullcache_size);
-        break;
-    }
-
-    case ACMOP_getssid: {
-        ssidref_t ssidref;
-
-        if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
-            ssidref = op->u.getssid.id.ssidref;
-        else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
-        {
-            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getssid.id.domainid);
-            if (!subj)
-            {
-                rc = -ESRCH; /* domain not found */
-                break;
-            }
-            if (subj->ssid == NULL)
-            {
-                rcu_unlock_domain(subj);
-                rc = -ESRCH;
-                break;
-            }
-            ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
-            rcu_unlock_domain(subj);
-        }
-        else
-        {
-            rc = -ESRCH;
-            break;
-        }
-        rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
-                          op->u.getssid.ssidbuf_size);
-        break;
-    }
-
-    case ACMOP_getdecision: {
-        ssidref_t ssidref1, ssidref2;
-
-        if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
-            ssidref1 = op->u.getdecision.id1.ssidref;
-        else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
-        {
-            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
-            if (!subj)
-            {
-                rc = -ESRCH; /* domain not found */
-                break;
-            }
-            if (subj->ssid == NULL)
-            {
-                rcu_unlock_domain(subj);
-                rc = -ESRCH;
-                break;
-            }
-            ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
-            rcu_unlock_domain(subj);
-        }
-        else
-        {
-            rc = -ESRCH;
-            break;
-        }
-        if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
-            ssidref2 = op->u.getdecision.id2.ssidref;
-        else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
-        {
-            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
-            if (!subj)
-            {
-                rc = -ESRCH; /* domain not found */
-                break;;
-            }
-            if (subj->ssid == NULL)
-            {
-                rcu_unlock_domain(subj);
-                rc = -ESRCH;
-                break;
-            }
-            ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
-            rcu_unlock_domain(subj);
-        }
-        else
-        {
-            rc = -ESRCH;
-            break;
-        }
-        rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
-
-        if (rc == ACM_ACCESS_PERMITTED)
-        {
-            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
-            rc = 0;
-        }
-        else if  (rc == ACM_ACCESS_DENIED)
-        {
-            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
-            rc = 0;
-        }
-        else
-            rc = -ESRCH;
-
-        if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
-            rc = -EFAULT;
-        break;
-    }
-
-    case ACMOP_chgpolicy: {
-        rc = acm_change_policy(&op->u.change_policy);
-        break;
-    }
-
-    case ACMOP_relabeldoms: {
-        rc = acm_relabel_domains(&op->u.relabel_doms);
-        break;
-    }
-
-    default:
-        rc = -ENOSYS;
-        break;
-    }
-
-    return rc;
-}
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/common/domain.c
--- a/xen/common/domain.c       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/common/domain.c       Fri Aug 31 11:41:49 2007 +0100
@@ -28,7 +28,6 @@
 #include <asm/debugger.h>
 #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. */
@@ -189,7 +188,7 @@ struct domain *domain_create(
     domid_t domid, unsigned int domcr_flags, ssidref_t ssidref)
 {
     struct domain *d, **pd;
-    enum { INIT_evtchn = 1, INIT_gnttab = 2, INIT_acm = 4, INIT_arch = 8 }; 
+    enum { INIT_evtchn = 1, INIT_gnttab = 2, INIT_arch = 8 }; 
     int init_status = 0;
 
     if ( (d = alloc_domain(domid)) == NULL )
@@ -215,10 +214,6 @@ struct domain *domain_create(
         if ( grant_table_create(d) != 0 )
             goto fail;
         init_status |= INIT_gnttab;
-
-        if ( acm_domain_create(d, ssidref) != 0 )
-            goto fail;
-        init_status |= INIT_acm;
     }
 
     if ( arch_domain_create(d) != 0 )
@@ -254,8 +249,6 @@ struct domain *domain_create(
     atomic_set(&d->refcnt, DOMAIN_DESTROYED);
     if ( init_status & INIT_arch )
         arch_domain_destroy(d);
-    if ( init_status & INIT_acm )
-        acm_domain_destroy(d);
     if ( init_status & INIT_gnttab )
         grant_table_destroy(d);
     if ( init_status & INIT_evtchn )
@@ -482,8 +475,6 @@ static void complete_domain_destroy(stru
         vcpu_destroy(v);
         sched_destroy_vcpu(v);
     }
-
-    acm_domain_destroy(d);
 
     rangeset_domain_destroy(d);
 
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/common/domctl.c
--- a/xen/common/domctl.c       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/common/domctl.c       Fri Aug 31 11:41:49 2007 +0100
@@ -23,7 +23,6 @@
 #include <xen/paging.h>
 #include <asm/current.h>
 #include <public/domctl.h>
-#include <acm/acm_hooks.h>
 #include <xsm/xsm.h>
 
 extern long arch_do_domctl(
@@ -124,11 +123,6 @@ void getdomaininfo(struct domain *d, str
     if ( is_hvm_domain(d) )
         info->flags |= XEN_DOMINF_hvm_guest;
 
-    if ( d->ssid != NULL )
-        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;
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/common/event_channel.c        Fri Aug 31 11:41:49 2007 +0100
@@ -29,7 +29,6 @@
 
 #include <public/xen.h>
 #include <public/event_channel.h>
-#include <acm/acm_hooks.h>
 #include <xsm/xsm.h>
 
 #define bucket_from_port(d,p) \
@@ -122,9 +121,6 @@ static long evtchn_alloc_unbound(evtchn_
     domid_t        dom = alloc->dom;
     long           rc;
 
-    if ( (rc = acm_pre_eventchannel_unbound(dom, alloc->remote_dom)) != 0 )
-        return rc;
-
     if ( dom == DOMID_SELF )
         dom = current->domain->domain_id;
     else if ( !IS_PRIV(current->domain) )
@@ -165,9 +161,6 @@ static long evtchn_bind_interdomain(evtc
     int            lport, rport = bind->remote_port;
     domid_t        rdom = bind->remote_dom;
     long           rc;
-
-    if ( (rc = acm_pre_eventchannel_interdomain(rdom)) != 0 )
-        return rc;
 
     if ( rdom == DOMID_SELF )
         rdom = current->domain->domain_id;
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/common/grant_table.c  Fri Aug 31 11:41:49 2007 +0100
@@ -32,7 +32,6 @@
 #include <xen/trace.h>
 #include <xen/guest_access.h>
 #include <xen/domain_page.h>
-#include <acm/acm_hooks.h>
 #include <xsm/xsm.h>
 
 #ifndef max_nr_grant_frames
@@ -209,12 +208,6 @@ __gnttab_map_grant_ref(
     {
         gdprintk(XENLOG_INFO, "Bad flags in grant map op (%x).\n", op->flags);
         op->status = GNTST_bad_gntref;
-        return;
-    }
-
-    if ( acm_pre_grant_map_ref(op->dom) )
-    {
-        op->status = GNTST_permission_denied;
         return;
     }
 
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/include/acm/acm_hooks.h
--- a/xen/include/acm/acm_hooks.h       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/include/acm/acm_hooks.h       Fri Aug 31 11:41:49 2007 +0100
@@ -145,8 +145,6 @@ static inline int acm_pre_grant_map_ref(
 { return 0; }
 static inline int acm_pre_grant_setup(domid_t id) 
 { return 0; }
-static inline int acm_init(char *policy_start, unsigned long policy_len)
-{ return 0; }
 static inline int acm_is_policy(char *buf, unsigned long len)
 { return 0; }
 static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
@@ -331,8 +329,6 @@ static inline int acm_authorization(ssid
 }
 
 
-extern int acm_init(char *policy_start, unsigned long policy_len);
-
 /* Return true iff buffer has an acm policy magic number.  */
 extern int acm_is_policy(char *buf, unsigned long len);
 
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/include/public/acm.h
--- a/xen/include/public/acm.h  Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/include/public/acm.h  Fri Aug 31 11:41:49 2007 +0100
@@ -150,8 +150,8 @@ struct acm_policy_version
  * tools that assume packed representations (e.g. the java tool)
  */
 struct acm_policy_buffer {
+    uint32_t magic;
     uint32_t policy_version; /* ACM_POLICY_VERSION */
-    uint32_t magic;
     uint32_t len;
     uint32_t policy_reference_offset;
     uint32_t primary_policy_code;
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/include/public/xen.h  Fri Aug 31 11:41:49 2007 +0100
@@ -69,7 +69,7 @@
 #define __HYPERVISOR_vcpu_op              24
 #define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
 #define __HYPERVISOR_mmuext_op            26
-#define __HYPERVISOR_acm_op               27
+#define __HYPERVISOR_xsm_op               27
 #define __HYPERVISOR_nmi_op               28
 #define __HYPERVISOR_sched_op             29
 #define __HYPERVISOR_callback_op          30
@@ -80,7 +80,6 @@
 #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 -r 993655d24b55 -r fa4d44c9d9f6 xen/include/xen/hypercall.h
--- a/xen/include/xen/hypercall.h       Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/include/xen/hypercall.h       Fri Aug 31 11:41:49 2007 +0100
@@ -12,7 +12,6 @@
 #include <public/domctl.h>
 #include <public/sysctl.h>
 #include <public/platform.h>
-#include <public/acm_ops.h>
 #include <public/event_channel.h>
 #include <asm/hypercall.h>
 #include <xsm/xsm.h>
@@ -98,10 +97,6 @@ do_vcpu_op(
     XEN_GUEST_HANDLE(void) arg);
 
 extern long
-do_acm_op(
-    XEN_GUEST_HANDLE(xen_acmctl_t) arg);
-
-extern long
 do_nmi_op(
     unsigned int cmd,
     XEN_GUEST_HANDLE(void) arg);
@@ -117,6 +112,10 @@ do_kexec_op(
     int arg1,
     XEN_GUEST_HANDLE(void) arg);
 
+extern long
+do_xsm_op(
+    XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
+
 #ifdef CONFIG_COMPAT
 
 extern int
@@ -126,8 +125,4 @@ compat_memory_op(
 
 #endif
 
-extern long
-do_xsm_op(
-    XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
-
 #endif /* __XEN_HYPERCALL_H__ */
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/xsm/Makefile
--- a/xen/xsm/Makefile  Fri Aug 31 11:37:20 2007 +0100
+++ b/xen/xsm/Makefile  Fri Aug 31 11:41:49 2007 +0100
@@ -5,3 +5,4 @@ endif
 endif
 
 subdir-$(FLASK_ENABLE) += flask
+subdir-$(ACM_SECURITY) += acm
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/Makefile      Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,7 @@
+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
+obj-y += acm_xsm_hooks.o
+obj-y += acm_ops.o
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/acm_chinesewall_hooks.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_chinesewall_hooks.c       Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,724 @@
+/****************************************************************
+ * 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 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/acm_core.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_core.c    Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,402 @@
+/****************************************************************
+ * 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>
+#include <xsm/xsm.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;
+
+extern struct xsm_operations acm_xsm_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
+acm_init(void)
+{
+    int ret = ACM_OK;
+
+    printk("ACM-XSM:  Initializing.\n");
+
+    /* first try to load the boot policy (uses its own locks) */
+    acm_setup(policy_buffer, policy_size, 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;
+    }
+
+    if (register_xsm(&acm_xsm_ops))
+        panic("ACM-XSM: Unable to register with XSM.\n");
+
+    return ret;
+}
+
+xsm_initcall(acm_init);
+
+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 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/acm_null_hooks.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_null_hooks.c      Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,95 @@
+/****************************************************************
+ * 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 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/acm_ops.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_ops.c     Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,212 @@
+/******************************************************************************
+ * acm_ops.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.
+ *
+ * Process acm command requests from guest OS.
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <public/acm.h>
+#include <public/acm_ops.h>
+#include <xen/sched.h>
+#include <xen/event.h>
+#include <xen/trace.h>
+#include <xen/console.h>
+#include <xen/guest_access.h>
+#include <acm/acm_hooks.h>
+
+#ifndef ACM_SECURITY
+
+long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
+{
+    return -ENOSYS;
+}
+
+#else
+
+int acm_authorize_acm_ops(struct domain *d)
+{
+    /* currently, policy management functions are restricted to privileged 
domains */
+    return (IS_PRIV(d) ? 0 : -EPERM);
+}
+
+
+long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
+{
+    long rc = -EFAULT;
+    struct xen_acmctl curop, *op = &curop;
+
+    if (acm_authorize_acm_ops(current->domain))
+        return -EPERM;
+
+    if ( copy_from_guest(op, u_acmctl, 1) )
+        return -EFAULT;
+
+    if (op->interface_version != ACM_INTERFACE_VERSION)
+        return -EACCES;
+
+    switch ( op->cmd )
+    {
+
+    case ACMOP_setpolicy: {
+        rc = acm_set_policy(op->u.setpolicy.pushcache,
+                            op->u.setpolicy.pushcache_size);
+        break;
+    }
+
+    case ACMOP_getpolicy: {
+        rc = acm_get_policy(op->u.getpolicy.pullcache,
+                            op->u.getpolicy.pullcache_size);
+        break;
+    }
+
+    case ACMOP_dumpstats: {
+        rc = acm_dump_statistics(op->u.dumpstats.pullcache,
+                                 op->u.dumpstats.pullcache_size);
+        break;
+    }
+
+    case ACMOP_getssid: {
+        ssidref_t ssidref;
+
+        if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
+            ssidref = op->u.getssid.id.ssidref;
+        else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
+        {
+            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getssid.id.domainid);
+            if (!subj)
+            {
+                rc = -ESRCH; /* domain not found */
+                break;
+            }
+            if (subj->ssid == NULL)
+            {
+                rcu_unlock_domain(subj);
+                rc = -ESRCH;
+                break;
+            }
+            ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
+            rcu_unlock_domain(subj);
+        }
+        else
+        {
+            rc = -ESRCH;
+            break;
+        }
+        rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
+                          op->u.getssid.ssidbuf_size);
+        break;
+    }
+
+    case ACMOP_getdecision: {
+        ssidref_t ssidref1, ssidref2;
+
+        if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
+            ssidref1 = op->u.getdecision.id1.ssidref;
+        else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
+        {
+            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
+            if (!subj)
+            {
+                rc = -ESRCH; /* domain not found */
+                break;
+            }
+            if (subj->ssid == NULL)
+            {
+                rcu_unlock_domain(subj);
+                rc = -ESRCH;
+                break;
+            }
+            ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
+            rcu_unlock_domain(subj);
+        }
+        else
+        {
+            rc = -ESRCH;
+            break;
+        }
+        if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
+            ssidref2 = op->u.getdecision.id2.ssidref;
+        else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
+        {
+            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
+            if (!subj)
+            {
+                rc = -ESRCH; /* domain not found */
+                break;;
+            }
+            if (subj->ssid == NULL)
+            {
+                rcu_unlock_domain(subj);
+                rc = -ESRCH;
+                break;
+            }
+            ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
+            rcu_unlock_domain(subj);
+        }
+        else
+        {
+            rc = -ESRCH;
+            break;
+        }
+        rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
+
+        if (rc == ACM_ACCESS_PERMITTED)
+        {
+            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
+            rc = 0;
+        }
+        else if  (rc == ACM_ACCESS_DENIED)
+        {
+            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
+            rc = 0;
+        }
+        else
+            rc = -ESRCH;
+
+        if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
+            rc = -EFAULT;
+        break;
+    }
+
+    case ACMOP_chgpolicy: {
+        rc = acm_change_policy(&op->u.change_policy);
+        break;
+    }
+
+    case ACMOP_relabeldoms: {
+        rc = acm_relabel_domains(&op->u.relabel_doms);
+        break;
+    }
+
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    return rc;
+}
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/acm_policy.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_policy.c  Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,876 @@
+/****************************************************************
+ * 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 993655d24b55 -r fa4d44c9d9f6 
xen/xsm/acm/acm_simple_type_enforcement_hooks.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c   Fri Aug 31 11:41:49 
2007 +0100
@@ -0,0 +1,914 @@
+/****************************************************************
+ * 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 993655d24b55 -r fa4d44c9d9f6 xen/xsm/acm/acm_xsm_hooks.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/xsm/acm/acm_xsm_hooks.c       Fri Aug 31 11:41:49 2007 +0100
@@ -0,0 +1,72 @@
+/****************************************************************
+ * acm_xsm_hooks.c
+ * 
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Author:
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ *
+ * Contributors: 
+ * Michael LeMay, <mdlemay@xxxxxxxxxxxxxx>
+ * George Coker, <gscoker@xxxxxxxxxxxxxx>
+ *
+ * sHype hooks for XSM based on the original ACM hooks.
+ *
+ * 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 <xsm/xsm.h>
+#include <acm/acm_hooks.h>
+#include <public/acm.h>
+
+static int acm_grant_mapref (struct domain *ld, struct domain *rd,
+                                                                 uint32_t 
flags) 
+{
+    domid_t id = rd->domain_id;
+
+    return acm_pre_grant_map_ref(id);
+}
+
+static int acm_evtchn_unbound (struct domain *d1, struct evtchn *chn1, domid_t 
id2) 
+{
+    domid_t id1 = d1->domain_id;
+    
+    return acm_pre_eventchannel_unbound(id1, id2);
+}
+
+static int acm_evtchn_interdomain (struct domain *d1, struct evtchn *chn1, 
+                                        struct domain *d2, struct evtchn 
*chn2) 
+{
+    domid_t id2 = d2->domain_id;
+
+    return acm_pre_eventchannel_interdomain(id2);
+}
+
+static void acm_security_domaininfo (struct domain *d, 
+                                        struct xen_domctl_getdomaininfo *info)
+{
+    if ( d->ssid != NULL )
+        info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
+    else    
+        info->ssidref = ACM_DEFAULT_SSID;
+}
+
+extern long do_acm_op(XEN_GUEST_HANDLE(xsm_op_t) arg);
+
+struct xsm_operations acm_xsm_ops = {
+    .domain_create = acm_domain_create,
+    .free_security_domain = acm_domain_destroy,
+
+    .grant_mapref = acm_grant_mapref,
+
+    .evtchn_unbound = acm_evtchn_unbound,
+    .evtchn_interdomain = acm_evtchn_interdomain,
+
+    .security_domaininfo = acm_security_domaininfo,
+
+    .__do_xsm_op = do_acm_op,
+};

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.