WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Xen Security Modules: ACM.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 07 Sep 2007 09:13:41 -0700
Delivery-date: Fri, 07 Sep 2007 09:22:02 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Xen Security Modules: ACM., Xen patchbot-unstable <=