ia64/xen-unstable

changeset 15818:fa4d44c9d9f6

Xen Security Modules: ACM.
Signed-off-by: George Coker <gscoker@alpha.ncsc.mil>
author kfraser@localhost.localdomain
date Fri Aug 31 11:41:49 2007 +0100 (2007-08-31)
parents 993655d24b55
children 7e7e0ea6a0bb
files tools/flask/loadpolicy/flask-loadpolicy tools/libxc/xc_acm.c tools/python/xen/util/xsm/xsm.py xen/Makefile xen/Rules.mk xen/acm/Makefile xen/acm/acm_chinesewall_hooks.c xen/acm/acm_core.c xen/acm/acm_null_hooks.c xen/acm/acm_policy.c xen/acm/acm_simple_type_enforcement_hooks.c xen/arch/x86/setup.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/compat/entry.S xen/arch/x86/x86_64/entry.S xen/common/Makefile xen/common/acm_ops.c xen/common/domain.c xen/common/domctl.c xen/common/event_channel.c xen/common/grant_table.c xen/include/acm/acm_hooks.h xen/include/public/acm.h xen/include/public/xen.h xen/include/xen/hypercall.h xen/xsm/Makefile xen/xsm/acm/Makefile xen/xsm/acm/acm_chinesewall_hooks.c xen/xsm/acm/acm_core.c xen/xsm/acm/acm_null_hooks.c xen/xsm/acm/acm_ops.c xen/xsm/acm/acm_policy.c xen/xsm/acm/acm_simple_type_enforcement_hooks.c xen/xsm/acm/acm_xsm_hooks.c
line diff
     1.1 Binary file tools/flask/loadpolicy/flask-loadpolicy has changed
     2.1 --- a/tools/libxc/xc_acm.c	Fri Aug 31 11:37:20 2007 +0100
     2.2 +++ b/tools/libxc/xc_acm.c	Fri Aug 31 11:41:49 2007 +0100
     2.3 @@ -81,7 +81,7 @@ int xc_acm_op(int xc_handle, int cmd, vo
     2.4      acmctl.cmd = cmd;
     2.5      acmctl.interface_version = ACM_INTERFACE_VERSION;
     2.6  
     2.7 -    hypercall.op = __HYPERVISOR_acm_op;
     2.8 +    hypercall.op = __HYPERVISOR_xsm_op;
     2.9      hypercall.arg[0] = (unsigned long)&acmctl;
    2.10      if ( lock_pages(&acmctl, sizeof(acmctl)) != 0)
    2.11      {
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/python/xen/util/xsm/xsm.py	Fri Aug 31 11:41:49 2007 +0100
     3.3 @@ -0,0 +1,9 @@
     3.4 +XEN_SECURITY_MODULE = "flask"
     3.5 +from xsm_core import *
     3.6 +
     3.7 +import xen.util.xsm.flask.flask as xsm_module
     3.8 +
     3.9 +xsm_init(xsm_module)
    3.10 +from xen.util.xsm.flask.flask import *
    3.11 +del xsm_module
    3.12 +
     4.1 --- a/xen/Makefile	Fri Aug 31 11:37:20 2007 +0100
     4.2 +++ b/xen/Makefile	Fri Aug 31 11:41:49 2007 +0100
     4.3 @@ -55,7 +55,6 @@ build install debug clean distclean csco
     4.4  	$(MAKE) -f $(BASEDIR)/Rules.mk -C include clean
     4.5  	$(MAKE) -f $(BASEDIR)/Rules.mk -C common clean
     4.6  	$(MAKE) -f $(BASEDIR)/Rules.mk -C drivers clean
     4.7 -	$(MAKE) -f $(BASEDIR)/Rules.mk -C acm clean
     4.8  	$(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean
     4.9  	$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean
    4.10  	rm -f include/asm *.o $(TARGET)* *~ core
    4.11 @@ -123,7 +122,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h
    4.12  build-headers:
    4.13  	$(MAKE) -C include/public/foreign
    4.14  
    4.15 -SUBDIRS = xsm acm arch/$(TARGET_ARCH) common drivers
    4.16 +SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers
    4.17  define all_sources
    4.18      ( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \
    4.19        find include -name 'asm-*' -prune -o -name '*.h' -print; \
     5.1 --- a/xen/Rules.mk	Fri Aug 31 11:37:20 2007 +0100
     5.2 +++ b/xen/Rules.mk	Fri Aug 31 11:41:49 2007 +0100
     5.3 @@ -53,7 +53,6 @@ HDRS  := $(filter-out %/asm-offsets.h,$(
     5.4  ALL_OBJS-y               += $(BASEDIR)/common/built_in.o
     5.5  ALL_OBJS-y               += $(BASEDIR)/drivers/built_in.o
     5.6  ALL_OBJS-y               += $(BASEDIR)/xsm/built_in.o
     5.7 -ALL_OBJS-$(ACM_SECURITY) += $(BASEDIR)/acm/built_in.o
     5.8  ALL_OBJS-y               += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o
     5.9  
    5.10  CFLAGS-y                += -g -D__XEN__
    5.11 @@ -62,7 +61,7 @@ CFLAGS-$(FLASK_ENABLE)    += -DFLASK_ENA
    5.12  CFLAGS-$(FLASK_DEVELOP)   += -DFLASK_DEVELOP
    5.13  CFLAGS-$(FLASK_BOOTPARAM) += -DFLASK_BOOTPARAM
    5.14  CFLAGS-$(FLASK_AVC_STATS) += -DFLASK_AVC_STATS
    5.15 -CFLAGS-$(ACM_SECURITY)  += -DACM_SECURITY
    5.16 +CFLAGS-$(ACM_SECURITY)    += -DACM_SECURITY -DXSM_MAGIC=0xbcde0100
    5.17  CFLAGS-$(verbose)       += -DVERBOSE
    5.18  CFLAGS-$(crash_debug)   += -DCRASH_DEBUG
    5.19  CFLAGS-$(perfc)         += -DPERF_COUNTERS
     6.1 --- a/xen/acm/Makefile	Fri Aug 31 11:37:20 2007 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,5 +0,0 @@
     6.4 -obj-y += acm_core.o 
     6.5 -obj-y += acm_policy.o
     6.6 -obj-y += acm_simple_type_enforcement_hooks.o
     6.7 -obj-y += acm_chinesewall_hooks.o
     6.8 -obj-y += acm_null_hooks.o
     7.1 --- a/xen/acm/acm_chinesewall_hooks.c	Fri Aug 31 11:37:20 2007 +0100
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,724 +0,0 @@
     7.4 -/****************************************************************
     7.5 - * acm_chinesewall_hooks.c
     7.6 - * 
     7.7 - * Copyright (C) 2005 IBM Corporation
     7.8 - *
     7.9 - * Author:
    7.10 - * Reiner Sailer <sailer@watson.ibm.com>
    7.11 - *
    7.12 - * Contributions:
    7.13 - * Stefan Berger <stefanb@watson.ibm.com>
    7.14 - *
    7.15 - * This program is free software; you can redistribute it and/or
    7.16 - * modify it under the terms of the GNU General Public License as
    7.17 - * published by the Free Software Foundation, version 2 of the
    7.18 - * License.
    7.19 - *
    7.20 - * sHype Chinese Wall Policy for Xen
    7.21 - *    This code implements the hooks that are called
    7.22 - *    throughout Xen operations and decides authorization
    7.23 - *    based on domain types and Chinese Wall conflict type 
    7.24 - *    sets. The CHWALL policy decides if a new domain can be started
    7.25 - *    based on the types of running domains and the type of the
    7.26 - *    new domain to be started. If the new domain's type is in
    7.27 - *    conflict with types of running domains, then this new domain
    7.28 - *    is not allowed to be created. A domain can have multiple types,
    7.29 - *    in which case all types of a new domain must be conflict-free
    7.30 - *    with all types of already running domains.
    7.31 - *
    7.32 - * indent -i4 -kr -nut
    7.33 - *
    7.34 - */
    7.35 -
    7.36 -#include <xen/config.h>
    7.37 -#include <xen/errno.h>
    7.38 -#include <xen/types.h>
    7.39 -#include <xen/lib.h>
    7.40 -#include <xen/delay.h>
    7.41 -#include <xen/sched.h>
    7.42 -#include <public/acm.h>
    7.43 -#include <asm/atomic.h>
    7.44 -#include <acm/acm_core.h>
    7.45 -#include <acm/acm_hooks.h>
    7.46 -#include <acm/acm_endian.h>
    7.47 -#include <acm/acm_core.h>
    7.48 -
    7.49 -ssidref_t dom0_chwall_ssidref = 0x0001;
    7.50 -
    7.51 -/* local cache structures for chinese wall policy */
    7.52 -struct chwall_binary_policy chwall_bin_pol;
    7.53 -
    7.54 -/*
    7.55 - * Initializing chinese wall policy (will be filled by policy partition
    7.56 - * using setpolicy command)
    7.57 - */
    7.58 -int acm_init_chwall_policy(void)
    7.59 -{
    7.60 -    /* minimal startup policy; policy write-locked already */
    7.61 -    chwall_bin_pol.max_types = 1;
    7.62 -    chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref;
    7.63 -    chwall_bin_pol.max_conflictsets = 1;
    7.64 -    chwall_bin_pol.ssidrefs =
    7.65 -        (domaintype_t *) xmalloc_array(domaintype_t,
    7.66 -                                       chwall_bin_pol.max_ssidrefs *
    7.67 -                                       chwall_bin_pol.max_types);
    7.68 -    chwall_bin_pol.conflict_sets =
    7.69 -        (domaintype_t *) xmalloc_array(domaintype_t,
    7.70 -                                       chwall_bin_pol.max_conflictsets *
    7.71 -                                       chwall_bin_pol.max_types);
    7.72 -    chwall_bin_pol.running_types =
    7.73 -        (domaintype_t *) xmalloc_array(domaintype_t,
    7.74 -                                       chwall_bin_pol.max_types);
    7.75 -    chwall_bin_pol.conflict_aggregate_set =
    7.76 -        (domaintype_t *) xmalloc_array(domaintype_t,
    7.77 -                                       chwall_bin_pol.max_types);
    7.78 -
    7.79 -    if ( (chwall_bin_pol.conflict_sets == NULL)
    7.80 -        || (chwall_bin_pol.running_types == NULL)
    7.81 -        || (chwall_bin_pol.ssidrefs == NULL)
    7.82 -        || (chwall_bin_pol.conflict_aggregate_set == NULL) )
    7.83 -        return ACM_INIT_SSID_ERROR;
    7.84 -
    7.85 -    /* initialize state */
    7.86 -    memset((void *) chwall_bin_pol.ssidrefs, 0,
    7.87 -           chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types *
    7.88 -           sizeof(domaintype_t));
    7.89 -    memset((void *) chwall_bin_pol.conflict_sets, 0,
    7.90 -           chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types *
    7.91 -           sizeof(domaintype_t));
    7.92 -    memset((void *) chwall_bin_pol.running_types, 0,
    7.93 -           chwall_bin_pol.max_types * sizeof(domaintype_t));
    7.94 -    memset((void *) chwall_bin_pol.conflict_aggregate_set, 0,
    7.95 -           chwall_bin_pol.max_types * sizeof(domaintype_t));
    7.96 -    return ACM_OK;
    7.97 -}
    7.98 -
    7.99 -
   7.100 -static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
   7.101 -{
   7.102 -    struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
   7.103 -    traceprintk("%s.\n", __func__);
   7.104 -
   7.105 -    if ( chwall_ssidp == NULL )
   7.106 -        return ACM_INIT_SSID_ERROR;
   7.107 -
   7.108 -    chwall_ssidp->chwall_ssidref =
   7.109 -        GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
   7.110 -
   7.111 -    if ( chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
   7.112 -    {
   7.113 -        printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset "
   7.114 -                "(0).\n",
   7.115 -                __func__, chwall_ssidp->chwall_ssidref);
   7.116 -        xfree(chwall_ssidp);
   7.117 -        return ACM_INIT_SSID_ERROR;
   7.118 -    }
   7.119 -    (*chwall_ssid) = chwall_ssidp;
   7.120 -    printkd("%s: determined chwall_ssidref to %x.\n",
   7.121 -            __func__, chwall_ssidp->chwall_ssidref);
   7.122 -    return ACM_OK;
   7.123 -}
   7.124 -
   7.125 -
   7.126 -static void chwall_free_domain_ssid(void *chwall_ssid)
   7.127 -{
   7.128 -    xfree(chwall_ssid);
   7.129 -    return;
   7.130 -}
   7.131 -
   7.132 -
   7.133 -/* dump chinese wall cache; policy read-locked already */
   7.134 -static int chwall_dump_policy(u8 * buf, u32 buf_size)
   7.135 -{
   7.136 -    struct acm_chwall_policy_buffer *chwall_buf =
   7.137 -        (struct acm_chwall_policy_buffer *) buf;
   7.138 -    int ret = 0;
   7.139 -
   7.140 -    if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
   7.141 -        return -EINVAL;
   7.142 -
   7.143 -    chwall_buf->chwall_max_types = cpu_to_be32(chwall_bin_pol.max_types);
   7.144 -    chwall_buf->chwall_max_ssidrefs = cpu_to_be32(chwall_bin_pol.max_ssidrefs);
   7.145 -    chwall_buf->policy_code = cpu_to_be32(ACM_CHINESE_WALL_POLICY);
   7.146 -    chwall_buf->chwall_ssid_offset =
   7.147 -        cpu_to_be32(sizeof(struct acm_chwall_policy_buffer));
   7.148 -    chwall_buf->chwall_max_conflictsets =
   7.149 -        cpu_to_be32(chwall_bin_pol.max_conflictsets);
   7.150 -    chwall_buf->chwall_conflict_sets_offset =
   7.151 -        cpu_to_be32(be32_to_cpu(chwall_buf->chwall_ssid_offset) +
   7.152 -              sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
   7.153 -              chwall_bin_pol.max_types);
   7.154 -    chwall_buf->chwall_running_types_offset =
   7.155 -        cpu_to_be32(be32_to_cpu(chwall_buf->chwall_conflict_sets_offset) +
   7.156 -              sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
   7.157 -              chwall_bin_pol.max_types);
   7.158 -    chwall_buf->chwall_conflict_aggregate_offset =
   7.159 -        cpu_to_be32(be32_to_cpu(chwall_buf->chwall_running_types_offset) +
   7.160 -              sizeof(domaintype_t) * chwall_bin_pol.max_types);
   7.161 -
   7.162 -    ret = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset) +
   7.163 -        sizeof(domaintype_t) * chwall_bin_pol.max_types;
   7.164 -
   7.165 -    ret = (ret + 7) & ~7;
   7.166 -
   7.167 -    if ( buf_size < ret )
   7.168 -        return -EINVAL;
   7.169 -
   7.170 -    /* now copy buffers over */
   7.171 -    arrcpy16((u16 *) (buf + be32_to_cpu(chwall_buf->chwall_ssid_offset)),
   7.172 -             chwall_bin_pol.ssidrefs,
   7.173 -             chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
   7.174 -
   7.175 -    arrcpy16((u16 *) (buf +
   7.176 -                      be32_to_cpu(chwall_buf->chwall_conflict_sets_offset)),
   7.177 -             chwall_bin_pol.conflict_sets,
   7.178 -             chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
   7.179 -
   7.180 -    arrcpy16((u16 *) (buf +
   7.181 -                      be32_to_cpu(chwall_buf->chwall_running_types_offset)),
   7.182 -             chwall_bin_pol.running_types, chwall_bin_pol.max_types);
   7.183 -
   7.184 -    arrcpy16((u16 *) (buf +
   7.185 -                      be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset)),
   7.186 -             chwall_bin_pol.conflict_aggregate_set,
   7.187 -             chwall_bin_pol.max_types);
   7.188 -    return ret;
   7.189 -}
   7.190 -
   7.191 -/*
   7.192 - * Adapt security state (running_types and conflict_aggregate_set) to all
   7.193 - * running domains; chwall_init_state is called when a policy is changed
   7.194 - * to bring the security information into a consistent state and to detect
   7.195 - * violations (return != 0) from a security point of view, we simulate
   7.196 - * that all running domains are re-started
   7.197 - */
   7.198 -static int
   7.199 -chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
   7.200 -                  domaintype_t * ssidrefs,
   7.201 -                  domaintype_t * conflict_sets,
   7.202 -                  domaintype_t * running_types,
   7.203 -                  domaintype_t * conflict_aggregate_set,
   7.204 -                  struct acm_sized_buffer *errors /* may be NULL */)
   7.205 -{
   7.206 -    int violation = 0, i, j;
   7.207 -    struct chwall_ssid *chwall_ssid;
   7.208 -    ssidref_t chwall_ssidref;
   7.209 -    struct acm_ssid_domain *rawssid;
   7.210 -
   7.211 -    read_lock(&ssid_list_rwlock);
   7.212 -
   7.213 -    /* go through all domains and adjust policy as if this domain was
   7.214 -     * started now
   7.215 -     */
   7.216 -    for_each_acmssid( rawssid )
   7.217 -    {
   7.218 -        chwall_ssid =
   7.219 -            GET_SSIDP(ACM_CHINESE_WALL_POLICY, rawssid);
   7.220 -        chwall_ssidref = chwall_ssid->chwall_ssidref;
   7.221 -        traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
   7.222 -                    __func__, d->domain_id, chwall_ssidref);
   7.223 -        /* a) adjust types ref-count for running domains */
   7.224 -        for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
   7.225 -            running_types[i] +=
   7.226 -                ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
   7.227 -
   7.228 -        /* b) check for conflict */
   7.229 -        for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
   7.230 -            if ( conflict_aggregate_set[i] &&
   7.231 -                 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i] )
   7.232 -            {
   7.233 -                printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
   7.234 -                       __func__, i);
   7.235 -                violation = 1;
   7.236 -
   7.237 -                acm_array_append_tuple(errors, ACM_CHWALL_CONFLICT, i);
   7.238 -
   7.239 -                goto out;
   7.240 -            }
   7.241 -
   7.242 -        /* set violation and break out of the loop */
   7.243 -        /* c) adapt conflict aggregate set for this domain
   7.244 -         *    (notice conflicts)
   7.245 -         */
   7.246 -        for ( i = 0; i < chwall_buf->chwall_max_conflictsets; i++ )
   7.247 -        {
   7.248 -            int common = 0;
   7.249 -            /* check if conflict_set_i and ssidref have common types */
   7.250 -            for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
   7.251 -                if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
   7.252 -                     ssidrefs[chwall_ssidref *
   7.253 -                              chwall_buf->chwall_max_types + j] )
   7.254 -                {
   7.255 -                    common = 1;
   7.256 -                    break;
   7.257 -                }
   7.258 -
   7.259 -            if ( common == 0 )
   7.260 -                continue;       /* try next conflict set */
   7.261 -
   7.262 -            /* now add types of the conflict set to conflict_aggregate_set
   7.263 -             * (except types in chwall_ssidref)
   7.264 -             */
   7.265 -            for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
   7.266 -                if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
   7.267 -                     !ssidrefs[chwall_ssidref *
   7.268 -                               chwall_buf->chwall_max_types + j] )
   7.269 -                    conflict_aggregate_set[j]++;
   7.270 -        }
   7.271 -    }
   7.272 - out:
   7.273 -    read_unlock(&ssid_list_rwlock);
   7.274 -    return violation;
   7.275 -    /* returning "violation != 0" means that the currently running set of
   7.276 -     * domains would not be possible if the new policy had been enforced
   7.277 -     * before starting them; for chinese wall, this means that the new
   7.278 -     * policy includes at least one conflict set of which more than one
   7.279 -     * type is currently running
   7.280 -     */
   7.281 -}
   7.282 -
   7.283 -
   7.284 -int
   7.285 -do_chwall_init_state_curr(struct acm_sized_buffer *errors)
   7.286 -{
   7.287 -    struct acm_chwall_policy_buffer chwall_buf =
   7.288 -    {
   7.289 -         /* only these two are important */
   7.290 -         .chwall_max_types        = chwall_bin_pol.max_types,
   7.291 -         .chwall_max_conflictsets = chwall_bin_pol.max_conflictsets,
   7.292 -    };
   7.293 -    /* reset running_types and aggregate set for recalculation */
   7.294 -    memset(chwall_bin_pol.running_types,
   7.295 -           0x0,
   7.296 -           sizeof(domaintype_t) * chwall_bin_pol.max_types);
   7.297 -    memset(chwall_bin_pol.conflict_aggregate_set,
   7.298 -           0x0,
   7.299 -           sizeof(domaintype_t) * chwall_bin_pol.max_types);
   7.300 -    return chwall_init_state(&chwall_buf,
   7.301 -                             chwall_bin_pol.ssidrefs,
   7.302 -                             chwall_bin_pol.conflict_sets,
   7.303 -                             chwall_bin_pol.running_types,
   7.304 -                             chwall_bin_pol.conflict_aggregate_set,
   7.305 -                             errors);
   7.306 -}
   7.307 -
   7.308 -/*
   7.309 - * Attempt to set the policy. This function must be called in test_only
   7.310 - * mode first to only perform checks. A second call then does the
   7.311 - * actual changes.
   7.312 - */
   7.313 -static int _chwall_update_policy(u8 *buf, u32 buf_size, int test_only,
   7.314 -                                 struct acm_sized_buffer *errors)
   7.315 -{
   7.316 -    int rc = -EFAULT;
   7.317 -    /* policy write-locked already */
   7.318 -    struct acm_chwall_policy_buffer *chwall_buf =
   7.319 -        (struct acm_chwall_policy_buffer *) buf;
   7.320 -    void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL,
   7.321 -         *conflict_aggregate_set = NULL;
   7.322 -
   7.323 -    /* 1. allocate new buffers */
   7.324 -    ssids =
   7.325 -        xmalloc_array(domaintype_t,
   7.326 -                      chwall_buf->chwall_max_types *
   7.327 -                      chwall_buf->chwall_max_ssidrefs);
   7.328 -    conflict_sets =
   7.329 -        xmalloc_array(domaintype_t,
   7.330 -                      chwall_buf->chwall_max_conflictsets *
   7.331 -                      chwall_buf->chwall_max_types);
   7.332 -    running_types =
   7.333 -        xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
   7.334 -    conflict_aggregate_set =
   7.335 -        xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
   7.336 -
   7.337 -    if ( (ssids == NULL) || (conflict_sets == NULL) ||
   7.338 -         (running_types == NULL) || (conflict_aggregate_set == NULL) )
   7.339 -        goto error_free;
   7.340 -
   7.341 -    /* 2. set new policy */
   7.342 -    if ( chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
   7.343 -         chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
   7.344 -         buf_size )
   7.345 -        goto error_free;
   7.346 -
   7.347 -    arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
   7.348 -           sizeof(domaintype_t),
   7.349 -           chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
   7.350 -
   7.351 -    if ( chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
   7.352 -         chwall_buf->chwall_max_types *
   7.353 -         chwall_buf->chwall_max_conflictsets > buf_size )
   7.354 -        goto error_free;
   7.355 -
   7.356 -    arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
   7.357 -           sizeof(domaintype_t),
   7.358 -           chwall_buf->chwall_max_types *
   7.359 -           chwall_buf->chwall_max_conflictsets);
   7.360 -
   7.361 -    /* we also use new state buffers since max_types can change */
   7.362 -    memset(running_types, 0,
   7.363 -           sizeof(domaintype_t) * chwall_buf->chwall_max_types);
   7.364 -    memset(conflict_aggregate_set, 0,
   7.365 -           sizeof(domaintype_t) * chwall_buf->chwall_max_types);
   7.366 -
   7.367 -    /* 3. now re-calculate the state for the new policy based on
   7.368 -     *    running domains; this can fail if new policy is conflicting
   7.369 -     *    with running domains
   7.370 -     */
   7.371 -    if ( chwall_init_state(chwall_buf, ssids,
   7.372 -                           conflict_sets, running_types,
   7.373 -                           conflict_aggregate_set,
   7.374 -                           errors))
   7.375 -    {
   7.376 -        printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
   7.377 -               __func__);
   7.378 -        goto error_free;        /* new policy conflicts with running domains */
   7.379 -    }
   7.380 -
   7.381 -    /* if this was only a test run, exit with ACM_OK */
   7.382 -    if ( test_only )
   7.383 -    {
   7.384 -        rc = ACM_OK;
   7.385 -        goto error_free;
   7.386 -    }
   7.387 -
   7.388 -    /* 4. free old policy buffers, replace with new ones */
   7.389 -    chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
   7.390 -    chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
   7.391 -    chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
   7.392 -    xfree(chwall_bin_pol.ssidrefs);
   7.393 -    xfree(chwall_bin_pol.conflict_aggregate_set);
   7.394 -    xfree(chwall_bin_pol.running_types);
   7.395 -    xfree(chwall_bin_pol.conflict_sets);
   7.396 -    chwall_bin_pol.ssidrefs = ssids;
   7.397 -    chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
   7.398 -    chwall_bin_pol.running_types = running_types;
   7.399 -    chwall_bin_pol.conflict_sets = conflict_sets;
   7.400 -
   7.401 -    return ACM_OK;
   7.402 -
   7.403 - error_free:
   7.404 -    if ( !test_only )
   7.405 -        printk("%s: ERROR setting policy.\n", __func__);
   7.406 -
   7.407 -    xfree(ssids);
   7.408 -    xfree(conflict_sets);
   7.409 -    xfree(running_types);
   7.410 -    xfree(conflict_aggregate_set);
   7.411 -    return rc;
   7.412 -}
   7.413 -
   7.414 -/*
   7.415 - * This function MUST be called before the chwall_ste_policy function!
   7.416 - */
   7.417 -static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
   7.418 -                              struct acm_sized_buffer *errors)
   7.419 -{
   7.420 -    struct acm_chwall_policy_buffer *chwall_buf =
   7.421 -        (struct acm_chwall_policy_buffer *) buf;
   7.422 -
   7.423 -    if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
   7.424 -        return -EINVAL;
   7.425 -
   7.426 -    /* rewrite the policy due to endianess */
   7.427 -    chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code);
   7.428 -    chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version);
   7.429 -    chwall_buf->chwall_max_types =
   7.430 -        be32_to_cpu(chwall_buf->chwall_max_types);
   7.431 -    chwall_buf->chwall_max_ssidrefs =
   7.432 -        be32_to_cpu(chwall_buf->chwall_max_ssidrefs);
   7.433 -    chwall_buf->chwall_max_conflictsets =
   7.434 -        be32_to_cpu(chwall_buf->chwall_max_conflictsets);
   7.435 -    chwall_buf->chwall_ssid_offset =
   7.436 -        be32_to_cpu(chwall_buf->chwall_ssid_offset);
   7.437 -    chwall_buf->chwall_conflict_sets_offset =
   7.438 -        be32_to_cpu(chwall_buf->chwall_conflict_sets_offset);
   7.439 -    chwall_buf->chwall_running_types_offset =
   7.440 -        be32_to_cpu(chwall_buf->chwall_running_types_offset);
   7.441 -    chwall_buf->chwall_conflict_aggregate_offset =
   7.442 -        be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset);
   7.443 -
   7.444 -    /* policy type and version checks */
   7.445 -    if ( (chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
   7.446 -         (chwall_buf->policy_version != ACM_CHWALL_VERSION) )
   7.447 -        return -EINVAL;
   7.448 -
   7.449 -    /* during boot dom0_chwall_ssidref is set */
   7.450 -    if ( is_bootpolicy &&
   7.451 -         (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs) )
   7.452 -        return -EINVAL;
   7.453 -
   7.454 -    return _chwall_update_policy(buf, buf_size, 1, errors);
   7.455 -}
   7.456 -
   7.457 -static int chwall_set_policy(u8 *buf, u32 buf_size)
   7.458 -{
   7.459 -    return _chwall_update_policy(buf, buf_size, 0, NULL);
   7.460 -}
   7.461 -
   7.462 -static int chwall_dump_stats(u8 * buf, u16 len)
   7.463 -{
   7.464 -    /* no stats for Chinese Wall Policy */
   7.465 -    return 0;
   7.466 -}
   7.467 -
   7.468 -static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
   7.469 -{
   7.470 -    int i;
   7.471 -
   7.472 -    /* fill in buffer */
   7.473 -    if ( chwall_bin_pol.max_types > len )
   7.474 -        return -EFAULT;
   7.475 -
   7.476 -    if ( ssidref >= chwall_bin_pol.max_ssidrefs )
   7.477 -        return -EFAULT;
   7.478 -
   7.479 -    /* read types for chwall ssidref */
   7.480 -    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
   7.481 -    {
   7.482 -        if ( chwall_bin_pol.
   7.483 -             ssidrefs[ssidref * chwall_bin_pol.max_types + i] )
   7.484 -            buf[i] = 1;
   7.485 -        else
   7.486 -            buf[i] = 0;
   7.487 -    }
   7.488 -    return chwall_bin_pol.max_types;
   7.489 -}
   7.490 -
   7.491 -/***************************
   7.492 - * Authorization functions
   7.493 - ***************************/
   7.494 -
   7.495 -/* -------- DOMAIN OPERATION HOOKS -----------*/
   7.496 -
   7.497 -static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
   7.498 -{
   7.499 -    ssidref_t chwall_ssidref;
   7.500 -    int i, j;
   7.501 -
   7.502 -    chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
   7.503 -
   7.504 -    if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
   7.505 -    {
   7.506 -        printk("%s: ERROR chwall_ssidref > max(%x).\n",
   7.507 -               __func__, chwall_bin_pol.max_ssidrefs - 1);
   7.508 -        return ACM_ACCESS_DENIED;
   7.509 -    }
   7.510 -
   7.511 -    /* A: chinese wall check for conflicts */
   7.512 -    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
   7.513 -        if ( chwall_bin_pol.conflict_aggregate_set[i] &&
   7.514 -             chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.515 -                                     chwall_bin_pol.max_types + i] )
   7.516 -        {
   7.517 -            printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
   7.518 -            return ACM_ACCESS_DENIED;
   7.519 -        }
   7.520 -
   7.521 -    /* B: chinese wall conflict set adjustment (so that other
   7.522 -     *    other domains simultaneously created are evaluated against
   7.523 -     *    this new set)
   7.524 -     */
   7.525 -    for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
   7.526 -    {
   7.527 -        int common = 0;
   7.528 -        /* check if conflict_set_i and ssidref have common types */
   7.529 -        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
   7.530 -            if ( chwall_bin_pol.
   7.531 -                 conflict_sets[i * chwall_bin_pol.max_types + j]
   7.532 -                 && chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.533 -                                            chwall_bin_pol.max_types + j] )
   7.534 -            {
   7.535 -                common = 1;
   7.536 -                break;
   7.537 -            }
   7.538 -        if ( common == 0 )
   7.539 -            continue;           /* try next conflict set */
   7.540 -        /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
   7.541 -        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
   7.542 -            if ( chwall_bin_pol.
   7.543 -                 conflict_sets[i * chwall_bin_pol.max_types + j]
   7.544 -                 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.545 -                                             chwall_bin_pol.max_types + j])
   7.546 -                 chwall_bin_pol.conflict_aggregate_set[j]++;
   7.547 -    }
   7.548 -    return ACM_ACCESS_PERMITTED;
   7.549 -}
   7.550 -
   7.551 -
   7.552 -static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
   7.553 -{
   7.554 -    int i, j;
   7.555 -    ssidref_t chwall_ssidref;
   7.556 -
   7.557 -    chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
   7.558 -    /* adjust types ref-count for running domains */
   7.559 -    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
   7.560 -        chwall_bin_pol.running_types[i] +=
   7.561 -            chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.562 -                                   chwall_bin_pol.max_types + i];
   7.563 -    if ( domid )
   7.564 -        return;
   7.565 -
   7.566 -    /* Xen does not call pre-create hook for DOM0;
   7.567 -     * to consider type conflicts of any domain with DOM0, we need
   7.568 -     * to adjust the conflict_aggregate for DOM0 here the same way it
   7.569 -     * is done for non-DOM0 domains in the pre-hook */
   7.570 -    printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
   7.571 -            __func__, ssidref, chwall_ssidref);
   7.572 -
   7.573 -    /* chinese wall conflict set adjustment (so that other
   7.574 -     *      other domains simultaneously created are evaluated against this new set)*/
   7.575 -    for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
   7.576 -    {
   7.577 -        int common = 0;
   7.578 -        /* check if conflict_set_i and ssidref have common types */
   7.579 -        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
   7.580 -            if ( chwall_bin_pol.
   7.581 -                 conflict_sets[i * chwall_bin_pol.max_types + j]
   7.582 -                 && chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.583 -                                            chwall_bin_pol.max_types + j] )
   7.584 -            {
   7.585 -                common = 1;
   7.586 -                break;
   7.587 -            }
   7.588 -
   7.589 -        if ( common == 0 )
   7.590 -        {
   7.591 -            /* try next conflict set */
   7.592 -            continue;
   7.593 -        }
   7.594 -
   7.595 -        /* now add types of the conflict set to conflict_aggregate_set
   7.596 -           (except types in chwall_ssidref) */
   7.597 -        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
   7.598 -            if ( chwall_bin_pol.
   7.599 -                 conflict_sets[i * chwall_bin_pol.max_types + j]
   7.600 -                 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.601 -                                             chwall_bin_pol.max_types + j] )
   7.602 -                chwall_bin_pol.conflict_aggregate_set[j]++;
   7.603 -    }
   7.604 -    return;
   7.605 -}
   7.606 -
   7.607 -
   7.608 -/*
   7.609 - * To be called when creating a domain. If this call is unsuccessful,
   7.610 - * no state changes have occurred (adjustments of counters etc.). If it
   7.611 - * was successful, state was changed and can be undone using
   7.612 - * chwall_domain_destroy.
   7.613 - */
   7.614 -static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref,
   7.615 -                                domid_t domid)
   7.616 -{
   7.617 -    int rc;
   7.618 -    read_lock(&acm_bin_pol_rwlock);
   7.619 -
   7.620 -    rc = _chwall_pre_domain_create(subject_ssid, ssidref);
   7.621 -    if ( rc == ACM_ACCESS_PERMITTED )
   7.622 -        _chwall_post_domain_create(domid, ssidref);
   7.623 -
   7.624 -    read_unlock(&acm_bin_pol_rwlock);
   7.625 -    return rc;
   7.626 -}
   7.627 -
   7.628 -/*
   7.629 - * This function undoes everything a successful call to
   7.630 - * chwall_domain_create has done.
   7.631 - */
   7.632 -static void chwall_domain_destroy(void *object_ssid, struct domain *d)
   7.633 -{
   7.634 -    int i, j;
   7.635 -    struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
   7.636 -                                                 (struct acm_ssid_domain *)
   7.637 -                                                 object_ssid);
   7.638 -    ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
   7.639 -
   7.640 -    read_lock(&acm_bin_pol_rwlock);
   7.641 -
   7.642 -    /* adjust running types set */
   7.643 -    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
   7.644 -        chwall_bin_pol.running_types[i] -=
   7.645 -            chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.646 -                                   chwall_bin_pol.max_types + i];
   7.647 -
   7.648 -    /* roll-back: re-adjust conflicting types aggregate */
   7.649 -    for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
   7.650 -    {
   7.651 -        int common = 0;
   7.652 -        /* check if conflict_set_i and ssidref have common types */
   7.653 -        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
   7.654 -            if ( chwall_bin_pol.conflict_sets[i * chwall_bin_pol.max_types + j]
   7.655 -                 && chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.656 -                                            chwall_bin_pol.max_types + j])
   7.657 -            {
   7.658 -                common = 1;
   7.659 -                break;
   7.660 -            }
   7.661 -        if ( common == 0 )
   7.662 -        {
   7.663 -            /* try next conflict set, this one does not include
   7.664 -               any type of chwall_ssidref */
   7.665 -            continue;
   7.666 -        }
   7.667 -
   7.668 -        /* now add types of the conflict set to conflict_aggregate_set
   7.669 -           (except types in chwall_ssidref) */
   7.670 -        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
   7.671 -            if ( chwall_bin_pol.
   7.672 -                 conflict_sets[i * chwall_bin_pol.max_types + j]
   7.673 -                 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
   7.674 -                                             chwall_bin_pol.max_types + j])
   7.675 -                chwall_bin_pol.conflict_aggregate_set[j]--;
   7.676 -    }
   7.677 -
   7.678 -    read_unlock(&acm_bin_pol_rwlock);
   7.679 -
   7.680 -    return;
   7.681 -}
   7.682 -
   7.683 -
   7.684 -static int chwall_is_default_policy(void)
   7.685 -{
   7.686 -    return ( (chwall_bin_pol.max_types    == 1 ) &&
   7.687 -             (chwall_bin_pol.max_ssidrefs == 2 ) );
   7.688 -}
   7.689 -
   7.690 -struct acm_operations acm_chinesewall_ops = {
   7.691 -    /* policy management services */
   7.692 -    .init_domain_ssid = chwall_init_domain_ssid,
   7.693 -    .free_domain_ssid = chwall_free_domain_ssid,
   7.694 -    .dump_binary_policy = chwall_dump_policy,
   7.695 -    .test_binary_policy = chwall_test_policy,
   7.696 -    .set_binary_policy = chwall_set_policy,
   7.697 -    .dump_statistics = chwall_dump_stats,
   7.698 -    .dump_ssid_types = chwall_dump_ssid_types,
   7.699 -    /* domain management control hooks */
   7.700 -    .domain_create = chwall_domain_create,
   7.701 -    .domain_destroy = chwall_domain_destroy,
   7.702 -    /* event channel control hooks */
   7.703 -    .pre_eventchannel_unbound = NULL,
   7.704 -    .fail_eventchannel_unbound = NULL,
   7.705 -    .pre_eventchannel_interdomain = NULL,
   7.706 -    .fail_eventchannel_interdomain = NULL,
   7.707 -    /* grant table control hooks */
   7.708 -    .pre_grant_map_ref = NULL,
   7.709 -    .fail_grant_map_ref = NULL,
   7.710 -    .pre_grant_setup = NULL,
   7.711 -    .fail_grant_setup = NULL,
   7.712 -    /* generic domain-requested decision hooks */
   7.713 -    .sharing = NULL,
   7.714 -    .authorization = NULL,
   7.715 -
   7.716 -    .is_default_policy = chwall_is_default_policy,
   7.717 -};
   7.718 -
   7.719 -/*
   7.720 - * Local variables:
   7.721 - * mode: C
   7.722 - * c-set-style: "BSD"
   7.723 - * c-basic-offset: 4
   7.724 - * tab-width: 4
   7.725 - * indent-tabs-mode: nil
   7.726 - * End:
   7.727 - */
     8.1 --- a/xen/acm/acm_core.c	Fri Aug 31 11:37:20 2007 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,392 +0,0 @@
     8.4 -/****************************************************************
     8.5 - * acm_core.c
     8.6 - * 
     8.7 - * Copyright (C) 2005 IBM Corporation
     8.8 - *
     8.9 - * Author:
    8.10 - * Reiner Sailer <sailer@watson.ibm.com>
    8.11 - *
    8.12 - * Contributors:
    8.13 - * Stefan Berger <stefanb@watson.ibm.com>
    8.14 - *
    8.15 - * This program is free software; you can redistribute it and/or
    8.16 - * modify it under the terms of the GNU General Public License as
    8.17 - * published by the Free Software Foundation, version 2 of the
    8.18 - * License.
    8.19 - *
    8.20 - * sHype access control module (ACM)
    8.21 - *       This file handles initialization of the ACM
    8.22 - *       as well as initializing/freeing security 
    8.23 - *       identifiers for domains (it calls on active
    8.24 - *       policy hook functions).
    8.25 - *
    8.26 - */
    8.27 -
    8.28 -#include <xen/config.h>
    8.29 -#include <xen/errno.h>
    8.30 -#include <xen/types.h>
    8.31 -#include <xen/lib.h>
    8.32 -#include <xen/delay.h>
    8.33 -#include <xen/sched.h>
    8.34 -#include <xen/multiboot.h>
    8.35 -#include <acm/acm_hooks.h>
    8.36 -#include <acm/acm_endian.h>
    8.37 -
    8.38 -/* debug: 
    8.39 - *   include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
    8.40 - *   define/undefine this constant to receive / suppress any
    8.41 - *   security hook debug output of sHype
    8.42 - *
    8.43 - *   include/public/acm.h defines a constant ACM_DEBUG
    8.44 - *   define/undefine this constant to receive non-hook-related
    8.45 - *   debug output.
    8.46 - */
    8.47 -
    8.48 -/* function prototypes */
    8.49 -void acm_init_chwall_policy(void);
    8.50 -void acm_init_ste_policy(void);
    8.51 -
    8.52 -extern struct acm_operations acm_chinesewall_ops, 
    8.53 -    acm_simple_type_enforcement_ops, acm_null_ops;
    8.54 -
    8.55 -/* global ACM policy  (now dynamically determined at boot time) */
    8.56 -u16 acm_active_security_policy = ACM_POLICY_UNDEFINED;
    8.57 -
    8.58 -/* global ops structs called by the hooks */
    8.59 -struct acm_operations *acm_primary_ops = NULL;
    8.60 -/* called in hook if-and-only-if primary succeeds */
    8.61 -struct acm_operations *acm_secondary_ops = NULL;
    8.62 -
    8.63 -/* acm global binary policy (points to 'local' primary and secondary policies */
    8.64 -struct acm_binary_policy acm_bin_pol;
    8.65 -/* acm binary policy lock */
    8.66 -DEFINE_RWLOCK(acm_bin_pol_rwlock);
    8.67 -
    8.68 -/* ACM's only accepted policy name during boot */
    8.69 -char polname[80];
    8.70 -char *acm_accepted_boot_policy_name = NULL;
    8.71 -
    8.72 -/* a lits of all chained ssid structures */
    8.73 -LIST_HEAD(ssid_list);
    8.74 -DEFINE_RWLOCK(ssid_list_rwlock);
    8.75 -
    8.76 -static void __init set_dom0_ssidref(const char *val)
    8.77 -{
    8.78 -    /* expected format:
    8.79 -         ssidref=<hex number>:<policy name>
    8.80 -         Policy name must not have a 'space'.
    8.81 -     */
    8.82 -    const char *c;
    8.83 -    int lo, hi;
    8.84 -    int i;
    8.85 -    int dom0_ssidref = simple_strtoull(val, &c, 0);
    8.86 -
    8.87 -    if (!strncmp(&c[0],":ACM:", 5)) {
    8.88 -        lo = dom0_ssidref & 0xffff;
    8.89 -        if (lo < ACM_MAX_NUM_TYPES && lo >= 1)
    8.90 -            dom0_chwall_ssidref = lo;
    8.91 -        hi = dom0_ssidref >> 16;
    8.92 -        if (hi < ACM_MAX_NUM_TYPES && hi >= 1)
    8.93 -            dom0_ste_ssidref = hi;
    8.94 -        for (i = 0; i < sizeof(polname); i++) {
    8.95 -            polname[i] = c[5+i];
    8.96 -            if (polname[i] == '\0' || polname[i] == '\t' ||
    8.97 -                polname[i] == '\n' || polname[i] == ' '  ||
    8.98 -                polname[i] == ':') {
    8.99 -                break;
   8.100 -            }
   8.101 -        }
   8.102 -        polname[i] = 0;
   8.103 -        acm_accepted_boot_policy_name = polname;
   8.104 -    }
   8.105 -}
   8.106 -
   8.107 -custom_param("ssidref", set_dom0_ssidref);
   8.108 -
   8.109 -int
   8.110 -acm_set_policy_reference(u8 *buf, u32 buf_size)
   8.111 -{
   8.112 -    char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer));
   8.113 -    struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
   8.114 -
   8.115 -    if (acm_accepted_boot_policy_name != NULL) {
   8.116 -        if (strcmp(acm_accepted_boot_policy_name, name)) {
   8.117 -            printk("Policy's name '%s' is not the expected one '%s'.\n",
   8.118 -                   name, acm_accepted_boot_policy_name);
   8.119 -            return ACM_ERROR;
   8.120 -        }
   8.121 -    }
   8.122 -
   8.123 -    acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len));
   8.124 -
   8.125 -    if (!acm_bin_pol.policy_reference_name)
   8.126 -        return -ENOMEM;
   8.127 -    strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len));
   8.128 -
   8.129 -    printk("%s: Activating policy %s\n", __func__,
   8.130 -           acm_bin_pol.policy_reference_name);
   8.131 -    return 0;
   8.132 -}
   8.133 -
   8.134 -int
   8.135 -acm_dump_policy_reference(u8 *buf, u32 buf_size)
   8.136 -{
   8.137 -    struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
   8.138 -    int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
   8.139 -
   8.140 -    ret = (ret + 7) & ~7;
   8.141 -    if (buf_size < ret)
   8.142 -        return -EINVAL;
   8.143 -
   8.144 -    memset(buf, 0, ret);
   8.145 -    pr_buf->len = cpu_to_be32(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
   8.146 -    strlcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
   8.147 -            acm_bin_pol.policy_reference_name,
   8.148 -            be32_to_cpu(pr_buf->len));
   8.149 -    return ret;
   8.150 -}
   8.151 -
   8.152 -int
   8.153 -acm_init_binary_policy(u32 policy_code)
   8.154 -{
   8.155 -    int ret = ACM_OK;
   8.156 -
   8.157 -    acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
   8.158 -    acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
   8.159 -
   8.160 -    write_lock(&acm_bin_pol_rwlock);
   8.161 -
   8.162 -    /* set primary policy component */
   8.163 -    switch ((policy_code) & 0x0f)
   8.164 -    {
   8.165 -
   8.166 -    case ACM_CHINESE_WALL_POLICY:
   8.167 -        acm_init_chwall_policy();
   8.168 -        acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
   8.169 -        acm_primary_ops = &acm_chinesewall_ops;
   8.170 -        break;
   8.171 -
   8.172 -    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
   8.173 -        acm_init_ste_policy();
   8.174 -        acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
   8.175 -        acm_primary_ops = &acm_simple_type_enforcement_ops;
   8.176 -        break;
   8.177 -
   8.178 -    case ACM_NULL_POLICY:
   8.179 -        acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
   8.180 -        acm_primary_ops = &acm_null_ops;
   8.181 -        break;
   8.182 -
   8.183 -    default:
   8.184 -        /* Unknown policy not allowed primary */
   8.185 -        ret = -EINVAL;
   8.186 -        goto out;
   8.187 -    }
   8.188 -
   8.189 -    /* secondary policy component part */
   8.190 -    switch ((policy_code) >> 4)
   8.191 -    {
   8.192 -
   8.193 -    case ACM_NULL_POLICY:
   8.194 -        acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
   8.195 -        acm_secondary_ops = &acm_null_ops;
   8.196 -        break;
   8.197 -
   8.198 -    case ACM_CHINESE_WALL_POLICY:
   8.199 -        if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
   8.200 -        {   /* not a valid combination */
   8.201 -            ret = -EINVAL;
   8.202 -            goto out;
   8.203 -        }
   8.204 -        acm_init_chwall_policy();
   8.205 -        acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
   8.206 -        acm_secondary_ops = &acm_chinesewall_ops;
   8.207 -        break;
   8.208 -
   8.209 -    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
   8.210 -        if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
   8.211 -        {   /* not a valid combination */
   8.212 -            ret = -EINVAL;
   8.213 -            goto out;
   8.214 -        }
   8.215 -        acm_init_ste_policy();
   8.216 -        acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
   8.217 -        acm_secondary_ops = &acm_simple_type_enforcement_ops;
   8.218 -        break;
   8.219 -
   8.220 -    default:
   8.221 -        ret = -EINVAL;
   8.222 -        goto out;
   8.223 -    }
   8.224 -
   8.225 - out:
   8.226 -    write_unlock(&acm_bin_pol_rwlock);
   8.227 -    return ret;
   8.228 -}
   8.229 -
   8.230 -int
   8.231 -acm_is_policy(char *buf, unsigned long len)
   8.232 -{
   8.233 -    struct acm_policy_buffer *pol;
   8.234 -
   8.235 -    if (buf == NULL || len < sizeof(struct acm_policy_buffer))
   8.236 -        return 0;
   8.237 -
   8.238 -    pol = (struct acm_policy_buffer *)buf;
   8.239 -    return be32_to_cpu(pol->magic) == ACM_MAGIC;
   8.240 -}
   8.241 -
   8.242 -
   8.243 -static int
   8.244 -acm_setup(char *policy_start,
   8.245 -          unsigned long policy_len,
   8.246 -          int is_bootpolicy)
   8.247 -{
   8.248 -    int rc = ACM_OK;
   8.249 -    struct acm_policy_buffer *pol;
   8.250 -
   8.251 -    if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
   8.252 -        return rc;
   8.253 -
   8.254 -    pol = (struct acm_policy_buffer *)policy_start;
   8.255 -    if (be32_to_cpu(pol->magic) != ACM_MAGIC)
   8.256 -        return rc;
   8.257 -
   8.258 -    rc = do_acm_set_policy((void *)policy_start, (u32)policy_len,
   8.259 -                           is_bootpolicy,
   8.260 -                           NULL, NULL, NULL);
   8.261 -    if (rc == ACM_OK)
   8.262 -    {
   8.263 -        printkd("Policy len  0x%lx, start at %p.\n",policy_len,policy_start);
   8.264 -    }
   8.265 -    else
   8.266 -    {
   8.267 -        printk("Invalid policy.\n");
   8.268 -        /* load default policy later */
   8.269 -        acm_active_security_policy = ACM_POLICY_UNDEFINED;
   8.270 -    }
   8.271 -    return rc;
   8.272 -}
   8.273 -
   8.274 -
   8.275 -int __init
   8.276 -acm_init(char *policy_start,
   8.277 -         unsigned long policy_len)
   8.278 -{
   8.279 -    int ret = ACM_OK;
   8.280 -
   8.281 -    /* first try to load the boot policy (uses its own locks) */
   8.282 -    acm_setup(policy_start, policy_len, 1);
   8.283 -
   8.284 -    /* a user-provided policy may have any name; only matched during boot */
   8.285 -    acm_accepted_boot_policy_name = NULL;
   8.286 -
   8.287 -    if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
   8.288 -    {
   8.289 -        printk("%s: Enforcing %s boot policy.\n", __func__,
   8.290 -               ACM_POLICY_NAME(acm_active_security_policy));
   8.291 -        goto out;
   8.292 -    }
   8.293 -    /* else continue with the minimal hardcoded default startup policy */
   8.294 -    printk("%s: Loading default policy (%s).\n",
   8.295 -           __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
   8.296 -
   8.297 -    /* (re-)set dom-0 ssidref to default */
   8.298 -    dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001;
   8.299 -
   8.300 -    if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
   8.301 -        ret = -EINVAL;
   8.302 -        goto out;
   8.303 -    }
   8.304 -    acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
   8.305 -    if (acm_active_security_policy != ACM_NULL_POLICY)
   8.306 -        acm_bin_pol.policy_reference_name = "DEFAULT";
   8.307 -    else
   8.308 -        acm_bin_pol.policy_reference_name = "NULL";
   8.309 -
   8.310 - out:
   8.311 -    if (ret != ACM_OK)
   8.312 -    {
   8.313 -        printk("%s: Error initializing policies.\n", __func__);
   8.314 -        /* here one could imagine a clean panic */
   8.315 -        return -EINVAL;
   8.316 -    }
   8.317 -    return ret;
   8.318 -}
   8.319 -
   8.320 -int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref)
   8.321 -{
   8.322 -    struct acm_ssid_domain *ssid;
   8.323 -    int ret1, ret2;
   8.324 -    if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
   8.325 -    {
   8.326 -        return ACM_INIT_SSID_ERROR;
   8.327 -    }
   8.328 -
   8.329 -    INIT_LIST_HEAD(&ssid->node);
   8.330 -    ssid->datatype       = ACM_DATATYPE_domain;
   8.331 -    ssid->subject        = subj;
   8.332 -    ssid->domainid       = subj->domain_id;
   8.333 -    ssid->primary_ssid   = NULL;
   8.334 -    ssid->secondary_ssid = NULL;
   8.335 -
   8.336 -    if (acm_active_security_policy != ACM_NULL_POLICY)
   8.337 -        ssid->ssidref = ssidref;
   8.338 -    else
   8.339 -        ssid->ssidref = ACM_DEFAULT_SSID;
   8.340 -
   8.341 -    subj->ssid           = ssid;
   8.342 -    /* now fill in primary and secondary parts; we only get here through hooks */
   8.343 -    if (acm_primary_ops->init_domain_ssid != NULL)
   8.344 -        ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
   8.345 -    else
   8.346 -        ret1 = ACM_OK;
   8.347 -
   8.348 -    if (acm_secondary_ops->init_domain_ssid != NULL)
   8.349 -        ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
   8.350 -    else
   8.351 -        ret2 = ACM_OK;
   8.352 -
   8.353 -    if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
   8.354 -    {
   8.355 -        printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
   8.356 -               __func__, subj->domain_id);
   8.357 -        acm_free_domain_ssid(ssid);
   8.358 -        return ACM_INIT_SSID_ERROR;
   8.359 -    }
   8.360 -
   8.361 -    printkd("%s: assigned domain %x the ssidref=%x.\n",
   8.362 -           __func__, subj->domain_id, ssid->ssidref);
   8.363 -    return ACM_OK;
   8.364 -}
   8.365 -
   8.366 -
   8.367 -void
   8.368 -acm_free_domain_ssid(struct acm_ssid_domain *ssid)
   8.369 -{
   8.370 -    /* domain is already gone, just ssid is left */
   8.371 -    if (ssid == NULL)
   8.372 -        return;
   8.373 -
   8.374 -    ssid->subject = NULL;
   8.375 -    if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
   8.376 -        acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
   8.377 -    ssid->primary_ssid = NULL;
   8.378 -    if (acm_secondary_ops->free_domain_ssid != NULL)
   8.379 -        acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
   8.380 -    ssid->secondary_ssid = NULL;
   8.381 -
   8.382 -    xfree(ssid);
   8.383 -    printkd("%s: Freed individual domain ssid (domain=%02x).\n",
   8.384 -            __func__, id);
   8.385 -}
   8.386 -
   8.387 -/*
   8.388 - * Local variables:
   8.389 - * mode: C
   8.390 - * c-set-style: "BSD"
   8.391 - * c-basic-offset: 4
   8.392 - * tab-width: 4
   8.393 - * indent-tabs-mode: nil
   8.394 - * End:
   8.395 - */
     9.1 --- a/xen/acm/acm_null_hooks.c	Fri Aug 31 11:37:20 2007 +0100
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,95 +0,0 @@
     9.4 -/****************************************************************
     9.5 - * acm_null_hooks.c
     9.6 - * 
     9.7 - * Copyright (C) 2005 IBM Corporation
     9.8 - *
     9.9 - * Author:
    9.10 - * Reiner Sailer <sailer@watson.ibm.com>
    9.11 - *
    9.12 - * This program is free software; you can redistribute it and/or
    9.13 - * modify it under the terms of the GNU General Public License as
    9.14 - * published by the Free Software Foundation, version 2 of the
    9.15 - * License.
    9.16 - */
    9.17 -
    9.18 -#include <acm/acm_hooks.h>
    9.19 -
    9.20 -static int
    9.21 -null_init_domain_ssid(void **ssid, ssidref_t ssidref)
    9.22 -{
    9.23 -    return ACM_OK;
    9.24 -}
    9.25 -
    9.26 -static void
    9.27 -null_free_domain_ssid(void *ssid)
    9.28 -{
    9.29 -    return;
    9.30 -}
    9.31 -
    9.32 -static int
    9.33 -null_dump_binary_policy(u8 *buf, u32 buf_size)
    9.34 -{ 
    9.35 -    return 0;
    9.36 -}
    9.37 -
    9.38 -static int
    9.39 -null_test_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
    9.40 -                        struct acm_sized_buffer *errors)
    9.41 -{
    9.42 -    return ACM_OK;
    9.43 -}
    9.44 -
    9.45 -static int
    9.46 -null_set_binary_policy(u8 *buf, u32 buf_size)
    9.47 -{ 
    9.48 -    return ACM_OK;
    9.49 -}
    9.50 - 
    9.51 -static int 
    9.52 -null_dump_stats(u8 *buf, u16 buf_size)
    9.53 -{
    9.54 -    /* no stats for NULL policy */
    9.55 -    return 0;
    9.56 -}
    9.57 -
    9.58 -static int
    9.59 -null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
    9.60 -{
    9.61 -    /* no types */
    9.62 -    return 0;
    9.63 -}
    9.64 -
    9.65 -
    9.66 -/* now define the hook structure similarly to LSM */
    9.67 -struct acm_operations acm_null_ops = {
    9.68 -    .init_domain_ssid = null_init_domain_ssid,
    9.69 -    .free_domain_ssid = null_free_domain_ssid,
    9.70 -    .dump_binary_policy = null_dump_binary_policy,
    9.71 -    .test_binary_policy = null_test_binary_policy,
    9.72 -    .set_binary_policy = null_set_binary_policy,
    9.73 -    .dump_statistics = null_dump_stats,
    9.74 -    .dump_ssid_types = null_dump_ssid_types,
    9.75 -    /* domain management control hooks */
    9.76 -    .domain_create = NULL,
    9.77 -    .domain_destroy = NULL,
    9.78 -    /* event channel control hooks */
    9.79 -    .pre_eventchannel_unbound = NULL,
    9.80 -    .fail_eventchannel_unbound = NULL,
    9.81 -    .pre_eventchannel_interdomain = NULL,
    9.82 -    .fail_eventchannel_interdomain = NULL,
    9.83 -    /* grant table control hooks */
    9.84 -    .pre_grant_map_ref = NULL,
    9.85 -    .fail_grant_map_ref = NULL,
    9.86 -    .pre_grant_setup = NULL,
    9.87 -    .fail_grant_setup = NULL
    9.88 -};
    9.89 -
    9.90 -/*
    9.91 - * Local variables:
    9.92 - * mode: C
    9.93 - * c-set-style: "BSD"
    9.94 - * c-basic-offset: 4
    9.95 - * tab-width: 4
    9.96 - * indent-tabs-mode: nil
    9.97 - * End:
    9.98 - */
    10.1 --- a/xen/acm/acm_policy.c	Fri Aug 31 11:37:20 2007 +0100
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,876 +0,0 @@
    10.4 -/****************************************************************
    10.5 - * acm_policy.c
    10.6 - * 
    10.7 - * Copyright (C) 2005-2007 IBM Corporation
    10.8 - *
    10.9 - * Author:
   10.10 - * Reiner Sailer <sailer@watson.ibm.com>
   10.11 - *
   10.12 - * Contributors:
   10.13 - * Stefan Berger <stefanb@watson.ibm.com>
   10.14 - *
   10.15 - * This program is free software; you can redistribute it and/or
   10.16 - * modify it under the terms of the GNU General Public License as
   10.17 - * published by the Free Software Foundation, version 2 of the
   10.18 - * License.
   10.19 - *
   10.20 - * sHype access control policy management for Xen.
   10.21 - *       This interface allows policy tools in authorized
   10.22 - *       domains to interact with the Xen access control module
   10.23 - * 
   10.24 - */
   10.25 -
   10.26 -#include <xen/config.h>
   10.27 -#include <xen/errno.h>
   10.28 -#include <xen/types.h>
   10.29 -#include <xen/lib.h>
   10.30 -#include <xen/delay.h>
   10.31 -#include <xen/sched.h>
   10.32 -#include <xen/guest_access.h>
   10.33 -#include <public/xen.h>
   10.34 -#include <acm/acm_core.h>
   10.35 -#include <public/acm_ops.h>
   10.36 -#include <acm/acm_hooks.h>
   10.37 -#include <acm/acm_endian.h>
   10.38 -#include <asm/current.h>
   10.39 -
   10.40 -static int acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
   10.41 -                                      struct acm_sized_buffer *errors);
   10.42 -static void acm_doms_change_ssidref(ssidref_t (*translator)
   10.43 -                                   (const struct acm_ssid_domain *,
   10.44 -                                    const struct acm_sized_buffer *),
   10.45 -                                    struct acm_sized_buffer *translation_map);
   10.46 -static void acm_doms_restore_ssidref(void);
   10.47 -static ssidref_t oldssid_to_newssid(const struct acm_ssid_domain *,
   10.48 -                                    const struct acm_sized_buffer *map);
   10.49 -
   10.50 -
   10.51 -int
   10.52 -acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
   10.53 -{
   10.54 -    u8 *policy_buffer = NULL;
   10.55 -    int ret = -EFAULT;
   10.56 -
   10.57 -    if ( buf_size < sizeof(struct acm_policy_buffer) )
   10.58 -        return -EFAULT;
   10.59 -
   10.60 -    /* copy buffer from guest domain */
   10.61 -    if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
   10.62 -        return -ENOMEM;
   10.63 -
   10.64 -    if ( copy_from_guest(policy_buffer, buf, buf_size) )
   10.65 -    {
   10.66 -        printk("%s: Error copying!\n",__func__);
   10.67 -        goto error_free;
   10.68 -    }
   10.69 -    ret = do_acm_set_policy(policy_buffer, buf_size, 0,
   10.70 -                            NULL, NULL, NULL);
   10.71 -
   10.72 - error_free:
   10.73 -    xfree(policy_buffer);
   10.74 -    return ret;
   10.75 -}
   10.76 -
   10.77 -
   10.78 -/*
   10.79 - * Update the policy of the running system by:
   10.80 - * - deleting ssidrefs that are not in the new policy anymore
   10.81 - *   -> no running domain may use such an ssidref
   10.82 - * - assign new ssidrefs to domains based on their old ssidrefs
   10.83 - *
   10.84 - */
   10.85 -static int
   10.86 -_acm_update_policy(void *buf, u32 buf_size, int is_bootpolicy,
   10.87 -                   struct acm_policy_buffer *pol,
   10.88 -                   struct acm_sized_buffer *deletions,
   10.89 -                   struct acm_sized_buffer *ssidchanges,
   10.90 -                   struct acm_sized_buffer *errors)
   10.91 -{
   10.92 -    uint32_t offset, length;
   10.93 -    static int require_update = 0;
   10.94 -
   10.95 -    write_lock(&acm_bin_pol_rwlock);
   10.96 -
   10.97 -    if (  require_update != 0 &&
   10.98 -        ( deletions == NULL || ssidchanges == NULL ) )
   10.99 -        goto error_lock_free;
  10.100 -
  10.101 -    require_update = 1;
  10.102 -    /*
  10.103 -       first some tests to check compatibility of new policy with
  10.104 -       current state of system/domains
  10.105 -     */
  10.106 -
  10.107 -    /* if ssidrefs are to be deleted, make sure no domain is using them */
  10.108 -    if ( deletions != NULL )
  10.109 -        if ( acm_check_deleted_ssidrefs(deletions, errors) )
  10.110 -            goto error_lock_free;
  10.111 -
  10.112 -    if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
  10.113 -        /* assign all running domains new ssidrefs as requested */
  10.114 -        acm_doms_change_ssidref(oldssid_to_newssid, ssidchanges);
  10.115 -
  10.116 -    /* test primary policy data with the new ssidrefs */
  10.117 -    offset = be32_to_cpu(pol->primary_buffer_offset);
  10.118 -    length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
  10.119 -
  10.120 -    if ( (offset + length) > buf_size ||
  10.121 -         acm_primary_ops->test_binary_policy(buf + offset, length,
  10.122 -                                             is_bootpolicy,
  10.123 -                                             errors))
  10.124 -        goto error_lock_free;
  10.125 -
  10.126 -    /* test secondary policy data with the new ssidrefs */
  10.127 -    offset = be32_to_cpu(pol->secondary_buffer_offset);
  10.128 -    length = be32_to_cpu(pol->len) - offset;
  10.129 -    if ( (offset + length) > buf_size ||
  10.130 -         acm_secondary_ops->test_binary_policy(buf + offset, length,
  10.131 -                                               is_bootpolicy,
  10.132 -                                               errors))
  10.133 -        goto error_lock_free;
  10.134 -
  10.135 -    /* end of testing --- now real updates */
  10.136 -
  10.137 -    offset = be32_to_cpu(pol->policy_reference_offset);
  10.138 -    length = be32_to_cpu(pol->primary_buffer_offset) - offset;
  10.139 -
  10.140 -    /* set label reference name */
  10.141 -    if ( (offset + length) > buf_size ||
  10.142 -         acm_set_policy_reference(buf + offset, length) )
  10.143 -        goto error_lock_free;
  10.144 -
  10.145 -    /* set primary policy data */
  10.146 -    offset = be32_to_cpu(pol->primary_buffer_offset);
  10.147 -    length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
  10.148 -
  10.149 -    if ( acm_primary_ops->set_binary_policy(buf + offset, length) )
  10.150 -        goto error_lock_free;
  10.151 -
  10.152 -    /* set secondary policy data */
  10.153 -    offset = be32_to_cpu(pol->secondary_buffer_offset);
  10.154 -    length = be32_to_cpu(pol->len) - offset;
  10.155 -    if ( acm_secondary_ops->set_binary_policy(buf + offset, length) )
  10.156 -        goto error_lock_free;
  10.157 -
  10.158 -    memcpy(&acm_bin_pol.xml_pol_version,
  10.159 -           &pol->xml_pol_version,
  10.160 -           sizeof(acm_bin_pol.xml_pol_version));
  10.161 -
  10.162 -    if ( acm_primary_ops->is_default_policy() &&
  10.163 -         acm_secondary_ops->is_default_policy() )
  10.164 -        require_update = 0;
  10.165 -
  10.166 -    write_unlock(&acm_bin_pol_rwlock);
  10.167 -
  10.168 -    return ACM_OK;
  10.169 -
  10.170 -error_lock_free:
  10.171 -    if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
  10.172 -    {
  10.173 -        acm_doms_restore_ssidref();
  10.174 -    }
  10.175 -    do_chwall_init_state_curr(NULL);
  10.176 -    write_unlock(&acm_bin_pol_rwlock);
  10.177 -
  10.178 -    return -EFAULT;
  10.179 -}
  10.180 -
  10.181 -
  10.182 -int
  10.183 -do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy,
  10.184 -                  struct acm_sized_buffer *deletions,
  10.185 -                  struct acm_sized_buffer *ssidchanges,
  10.186 -                  struct acm_sized_buffer *errors)
  10.187 -{
  10.188 -    struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
  10.189 -
  10.190 -    /* some sanity checking */
  10.191 -    if ( (be32_to_cpu(pol->magic) != ACM_MAGIC) ||
  10.192 -         (buf_size != be32_to_cpu(pol->len)) ||
  10.193 -         (be32_to_cpu(pol->policy_version) != ACM_POLICY_VERSION) )
  10.194 -    {
  10.195 -        printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
  10.196 -        goto error_free;
  10.197 -    }
  10.198 -
  10.199 -    if ( acm_active_security_policy == ACM_POLICY_UNDEFINED )
  10.200 -    {
  10.201 -        /* setup the policy with the boot policy */
  10.202 -        if ( acm_init_binary_policy(
  10.203 -                             (be32_to_cpu(pol->secondary_policy_code) << 4) |
  10.204 -                              be32_to_cpu(pol->primary_policy_code)) )
  10.205 -        {
  10.206 -            goto error_free;
  10.207 -        }
  10.208 -        acm_active_security_policy = (acm_bin_pol.secondary_policy_code << 4) |
  10.209 -                                      acm_bin_pol.primary_policy_code;
  10.210 -    }
  10.211 -
  10.212 -    /* once acm_active_security_policy is set, it cannot be changed */
  10.213 -    if ( (be32_to_cpu(pol->primary_policy_code) !=
  10.214 -                                        acm_bin_pol.primary_policy_code) ||
  10.215 -         (be32_to_cpu(pol->secondary_policy_code) !=
  10.216 -                                        acm_bin_pol.secondary_policy_code) )
  10.217 -    {
  10.218 -        printkd("%s: Wrong policy type in boot policy!\n", __func__);
  10.219 -        goto error_free;
  10.220 -    }
  10.221 -
  10.222 -    return _acm_update_policy(buf, buf_size, is_bootpolicy,
  10.223 -                              pol,
  10.224 -                              deletions, ssidchanges,
  10.225 -                              errors);
  10.226 -
  10.227 - error_free:
  10.228 -    printk("%s: Error setting policy.\n", __func__);
  10.229 -    return -EFAULT;
  10.230 -}
  10.231 -
  10.232 -int
  10.233 -acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
  10.234 -{ 
  10.235 -    u8 *policy_buffer;
  10.236 -    int ret;
  10.237 -    struct acm_policy_buffer *bin_pol;
  10.238 -
  10.239 -    if ( buf_size < sizeof(struct acm_policy_buffer) )
  10.240 -        return -EFAULT;
  10.241 -
  10.242 -    if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
  10.243 -        return -ENOMEM;
  10.244 -
  10.245 -    read_lock(&acm_bin_pol_rwlock);
  10.246 -
  10.247 -    bin_pol = (struct acm_policy_buffer *)policy_buffer;
  10.248 -    bin_pol->magic = cpu_to_be32(ACM_MAGIC);
  10.249 -    bin_pol->primary_policy_code =
  10.250 -                                cpu_to_be32(acm_bin_pol.primary_policy_code);
  10.251 -    bin_pol->secondary_policy_code =
  10.252 -                                cpu_to_be32(acm_bin_pol.secondary_policy_code);
  10.253 -
  10.254 -    bin_pol->len = cpu_to_be32(sizeof(struct acm_policy_buffer));
  10.255 -    bin_pol->policy_reference_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  10.256 -    bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  10.257 -    bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  10.258 -
  10.259 -    memcpy(&bin_pol->xml_pol_version,
  10.260 -           &acm_bin_pol.xml_pol_version,
  10.261 -           sizeof(struct acm_policy_version));
  10.262 -
  10.263 -    ret = acm_dump_policy_reference(
  10.264 -               policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset),
  10.265 -               buf_size - be32_to_cpu(bin_pol->policy_reference_offset));
  10.266 -
  10.267 -    if ( ret < 0 )
  10.268 -        goto error_free_unlock;
  10.269 -
  10.270 -    bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
  10.271 -    bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  10.272 -
  10.273 -    ret = acm_primary_ops->dump_binary_policy(
  10.274 -                 policy_buffer + be32_to_cpu(bin_pol->primary_buffer_offset),
  10.275 -                 buf_size - be32_to_cpu(bin_pol->primary_buffer_offset));
  10.276 -
  10.277 -    if ( ret < 0 )
  10.278 -        goto error_free_unlock;
  10.279 -
  10.280 -    bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
  10.281 -    bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  10.282 -
  10.283 -    ret = acm_secondary_ops->dump_binary_policy(
  10.284 -               policy_buffer + be32_to_cpu(bin_pol->secondary_buffer_offset),
  10.285 -               buf_size - be32_to_cpu(bin_pol->secondary_buffer_offset));
  10.286 -
  10.287 -    if ( ret < 0 )
  10.288 -        goto error_free_unlock;
  10.289 -
  10.290 -    bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
  10.291 -    if ( copy_to_guest(buf, policy_buffer, be32_to_cpu(bin_pol->len)) )
  10.292 -        goto error_free_unlock;
  10.293 -
  10.294 -    read_unlock(&acm_bin_pol_rwlock);
  10.295 -    xfree(policy_buffer);
  10.296 -
  10.297 -    return ACM_OK;
  10.298 -
  10.299 - error_free_unlock:
  10.300 -    read_unlock(&acm_bin_pol_rwlock);
  10.301 -    printk("%s: Error getting policy.\n", __func__);
  10.302 -    xfree(policy_buffer);
  10.303 -
  10.304 -    return -EFAULT;
  10.305 -}
  10.306 -
  10.307 -int
  10.308 -acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
  10.309 -{ 
  10.310 -    /* send stats to user space */
  10.311 -    u8 *stats_buffer;
  10.312 -    int len1, len2;
  10.313 -    struct acm_stats_buffer acm_stats;
  10.314 -
  10.315 -    if ( (stats_buffer = xmalloc_array(u8, buf_size)) == NULL )
  10.316 -        return -ENOMEM;
  10.317 -
  10.318 -    read_lock(&acm_bin_pol_rwlock);
  10.319 -     
  10.320 -    len1 = acm_primary_ops->dump_statistics(
  10.321 -                             stats_buffer + sizeof(struct acm_stats_buffer),
  10.322 -                             buf_size - sizeof(struct acm_stats_buffer));
  10.323 -    if ( len1 < 0 )
  10.324 -        goto error_lock_free;
  10.325 -      
  10.326 -    len2 = acm_secondary_ops->dump_statistics(
  10.327 -                      stats_buffer + sizeof(struct acm_stats_buffer) + len1,
  10.328 -                      buf_size - sizeof(struct acm_stats_buffer) - len1);
  10.329 -    if ( len2 < 0 )
  10.330 -        goto error_lock_free;
  10.331 -
  10.332 -    acm_stats.magic = cpu_to_be32(ACM_MAGIC);
  10.333 -    acm_stats.primary_policy_code =
  10.334 -                           cpu_to_be32(acm_bin_pol.primary_policy_code);
  10.335 -    acm_stats.secondary_policy_code =
  10.336 -                           cpu_to_be32(acm_bin_pol.secondary_policy_code);
  10.337 -    acm_stats.primary_stats_offset =
  10.338 -                           cpu_to_be32(sizeof(struct acm_stats_buffer));
  10.339 -    acm_stats.secondary_stats_offset =
  10.340 -                           cpu_to_be32(sizeof(struct acm_stats_buffer) + len1);
  10.341 -    acm_stats.len = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1 + len2);
  10.342 -
  10.343 -    memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
  10.344 -
  10.345 -    if ( copy_to_guest(buf,
  10.346 -                       stats_buffer,
  10.347 -                       sizeof(struct acm_stats_buffer) + len1 + len2) )
  10.348 -        goto error_lock_free;
  10.349 -
  10.350 -    read_unlock(&acm_bin_pol_rwlock);
  10.351 -    xfree(stats_buffer);
  10.352 -
  10.353 -    return ACM_OK;
  10.354 -
  10.355 - error_lock_free:
  10.356 -    read_unlock(&acm_bin_pol_rwlock);
  10.357 -    xfree(stats_buffer);
  10.358 -
  10.359 -    return -EFAULT;
  10.360 -}
  10.361 -
  10.362 -
  10.363 -int
  10.364 -acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
  10.365 -{
  10.366 -    /* send stats to user space */
  10.367 -    u8 *ssid_buffer;
  10.368 -    int ret;
  10.369 -    struct acm_ssid_buffer *acm_ssid;
  10.370 -    if ( buf_size < sizeof(struct acm_ssid_buffer) )
  10.371 -        return -EFAULT;
  10.372 -
  10.373 -    if ( (ssid_buffer = xmalloc_array(u8, buf_size)) == NULL )
  10.374 -        return -ENOMEM;
  10.375 -
  10.376 -    read_lock(&acm_bin_pol_rwlock);
  10.377 -
  10.378 -    acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
  10.379 -    acm_ssid->len = sizeof(struct acm_ssid_buffer);
  10.380 -    acm_ssid->ssidref = ssidref;
  10.381 -    acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
  10.382 -    acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
  10.383 -
  10.384 -    acm_ssid->policy_reference_offset = acm_ssid->len;
  10.385 -    ret = acm_dump_policy_reference(
  10.386 -                          ssid_buffer + acm_ssid->policy_reference_offset,
  10.387 -                          buf_size - acm_ssid->policy_reference_offset);
  10.388 -    if ( ret < 0 )
  10.389 -        goto error_free_unlock;
  10.390 -
  10.391 -    acm_ssid->len += ret;
  10.392 -    acm_ssid->primary_types_offset = acm_ssid->len;
  10.393 -
  10.394 -    /* ret >= 0 --> ret == max_types */
  10.395 -    ret = acm_primary_ops->dump_ssid_types(
  10.396 -                                 ACM_PRIMARY(ssidref),
  10.397 -                                 ssid_buffer + acm_ssid->primary_types_offset,
  10.398 -                                 buf_size - acm_ssid->primary_types_offset);
  10.399 -    if ( ret < 0 )
  10.400 -        goto error_free_unlock;
  10.401 -
  10.402 -    acm_ssid->len += ret;
  10.403 -    acm_ssid->primary_max_types = ret;
  10.404 -    acm_ssid->secondary_types_offset = acm_ssid->len;
  10.405 -
  10.406 -    ret = acm_secondary_ops->dump_ssid_types(
  10.407 -                             ACM_SECONDARY(ssidref),
  10.408 -                             ssid_buffer + acm_ssid->secondary_types_offset,
  10.409 -                             buf_size - acm_ssid->secondary_types_offset);
  10.410 -    if ( ret < 0 )
  10.411 -        goto error_free_unlock;
  10.412 -
  10.413 -    acm_ssid->len += ret;
  10.414 -    acm_ssid->secondary_max_types = ret;
  10.415 -
  10.416 -    if ( copy_to_guest(buf, ssid_buffer, acm_ssid->len) )
  10.417 -        goto error_free_unlock;
  10.418 -
  10.419 -    read_unlock(&acm_bin_pol_rwlock);
  10.420 -    xfree(ssid_buffer);
  10.421 -
  10.422 -    return ACM_OK;
  10.423 -
  10.424 - error_free_unlock:
  10.425 -    read_unlock(&acm_bin_pol_rwlock);
  10.426 -    printk("%s: Error getting ssid.\n", __func__);
  10.427 -    xfree(ssid_buffer);
  10.428 -
  10.429 -    return -ENOMEM;
  10.430 -}
  10.431 -
  10.432 -int
  10.433 -acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook)
  10.434 -{
  10.435 -    int ret = ACM_ACCESS_DENIED;
  10.436 -    switch ( hook )
  10.437 -    {
  10.438 -
  10.439 -    case ACMHOOK_sharing:
  10.440 -        /* Sharing hook restricts access in STE policy only */
  10.441 -        ret = acm_sharing(ssidref1, ssidref2);
  10.442 -        break;
  10.443 -
  10.444 -    case ACMHOOK_authorization:
  10.445 -        ret = acm_authorization(ssidref1, ssidref2);
  10.446 -        break;
  10.447 -
  10.448 -    default:
  10.449 -        /* deny */
  10.450 -        break;
  10.451 -    }
  10.452 -
  10.453 -    printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n",
  10.454 -            __func__, ssidref1, ssidref2,
  10.455 -            (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED");
  10.456 -
  10.457 -    return ret;
  10.458 -}
  10.459 -
  10.460 -
  10.461 -
  10.462 -/*
  10.463 -   Check if an ssidref of the current policy type is being used by any
  10.464 -   domain.
  10.465 - */
  10.466 -static int
  10.467 -acm_check_used_ssidref(uint32_t policy_type, uint32_t search_ssidref,
  10.468 -                       struct acm_sized_buffer *errors)
  10.469 -{
  10.470 -    int rc = 0;
  10.471 -    struct acm_ssid_domain *rawssid;
  10.472 -
  10.473 -    read_lock(&ssid_list_rwlock);
  10.474 -
  10.475 -    for_each_acmssid( rawssid )
  10.476 -    {
  10.477 -        ssidref_t ssidref;
  10.478 -        void *s = GET_SSIDP(policy_type, rawssid);
  10.479 -
  10.480 -        if ( policy_type == ACM_CHINESE_WALL_POLICY )
  10.481 -        {
  10.482 -            ssidref = ((struct chwall_ssid *)s)->chwall_ssidref;
  10.483 -        } else {
  10.484 -            ssidref = ((struct ste_ssid *)s)->ste_ssidref;
  10.485 -        }
  10.486 -        gdprintk(XENLOG_INFO,"domid=%d: search ssidref=%d, ssidref=%d\n",
  10.487 -                 rawssid->domainid,search_ssidref,ssidref);
  10.488 -        if ( ssidref == search_ssidref )
  10.489 -        {
  10.490 -            /* one is enough */
  10.491 -            acm_array_append_tuple(errors, ACM_SSIDREF_IN_USE, search_ssidref);
  10.492 -            rc = 1;
  10.493 -            break;
  10.494 -        }
  10.495 -    }
  10.496 -
  10.497 -    read_unlock(&ssid_list_rwlock);
  10.498 -
  10.499 -    return rc;
  10.500 -}
  10.501 -
  10.502 -
  10.503 -/*
  10.504 - * Translate a current ssidref into its future representation under
  10.505 - * the new policy.
  10.506 - * The map provides translation of ssidrefs from old to new in tuples
  10.507 - * of (old ssidref, new ssidref).
  10.508 - */
  10.509 -static ssidref_t
  10.510 -oldssid_to_newssid(const struct acm_ssid_domain *rawssid,
  10.511 -                   const struct acm_sized_buffer *map)
  10.512 -{
  10.513 -    uint i;
  10.514 -
  10.515 -    if ( rawssid != NULL )
  10.516 -    {
  10.517 -        ssidref_t ssid = rawssid->ssidref & 0xffff;
  10.518 -        for ( i = 0; i + 1 < map->num_items; i += 2 )
  10.519 -        {
  10.520 -            if ( map->array[i] == ssid )
  10.521 -            {
  10.522 -                return (map->array[i+1] << 16 | map->array[i+1]);
  10.523 -            }
  10.524 -        }
  10.525 -    }
  10.526 -    return ACM_INVALID_SSIDREF;
  10.527 -}
  10.528 -
  10.529 -
  10.530 -/*
  10.531 - * Assign an ssidref to the CHWALL policy component of the domain
  10.532 - */
  10.533 -static void
  10.534 -acm_pri_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
  10.535 -                              ssidref_t new_ssid)
  10.536 -{
  10.537 -    struct chwall_ssid *chwall = (struct chwall_ssid *)rawssid->primary_ssid;
  10.538 -    chwall->chwall_ssidref = new_ssid;
  10.539 -}
  10.540 -
  10.541 -
  10.542 -/*
  10.543 - * Assign an ssidref to the STE policy component of the domain
  10.544 - */
  10.545 -static void
  10.546 -acm_sec_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
  10.547 -                              ssidref_t new_ssid)
  10.548 -{
  10.549 -    struct ste_ssid *ste = (struct ste_ssid *)rawssid->secondary_ssid;
  10.550 -    ste->ste_ssidref = new_ssid;
  10.551 -}
  10.552 -
  10.553 -/*
  10.554 -   Change the ssidrefs on each domain using a passed translation function;
  10.555 - */
  10.556 -static void
  10.557 -acm_doms_change_ssidref(ssidref_t (*translator_fn)
  10.558 -                          (const struct acm_ssid_domain *,
  10.559 -                           const struct acm_sized_buffer *),
  10.560 -                        struct acm_sized_buffer *translation_map)
  10.561 -{
  10.562 -    struct acm_ssid_domain *rawssid;
  10.563 -
  10.564 -    write_lock(&ssid_list_rwlock);
  10.565 -
  10.566 -    for_each_acmssid( rawssid )
  10.567 -    {
  10.568 -        ssidref_t new_ssid;
  10.569 -
  10.570 -        rawssid->old_ssidref = rawssid->ssidref;
  10.571 -
  10.572 -        new_ssid = translator_fn(rawssid, translation_map);
  10.573 -        if ( new_ssid == ACM_INVALID_SSIDREF )
  10.574 -        {
  10.575 -            /* means no mapping found, so no change -- old = new */
  10.576 -            continue;
  10.577 -        }
  10.578 -
  10.579 -        acm_pri_policy_assign_ssidref(rawssid, ACM_PRIMARY  (new_ssid) );
  10.580 -        acm_sec_policy_assign_ssidref(rawssid, ACM_SECONDARY(new_ssid) );
  10.581 -
  10.582 -        rawssid->ssidref = new_ssid;
  10.583 -    }
  10.584 -
  10.585 -    write_unlock(&ssid_list_rwlock);
  10.586 -}
  10.587 -
  10.588 -/*
  10.589 - * Restore the previous ssidref values on all domains
  10.590 - */
  10.591 -static void
  10.592 -acm_doms_restore_ssidref(void)
  10.593 -{
  10.594 -    struct acm_ssid_domain *rawssid;
  10.595 -
  10.596 -    write_lock(&ssid_list_rwlock);
  10.597 -
  10.598 -    for_each_acmssid( rawssid )
  10.599 -    {
  10.600 -        ssidref_t old_ssid;
  10.601 -
  10.602 -        if ( rawssid->old_ssidref == rawssid->ssidref )
  10.603 -            continue;
  10.604 -
  10.605 -        old_ssid = rawssid->old_ssidref & 0xffff;
  10.606 -        rawssid->ssidref = rawssid->old_ssidref;
  10.607 -
  10.608 -        acm_pri_policy_assign_ssidref(rawssid, old_ssid);
  10.609 -        acm_sec_policy_assign_ssidref(rawssid, old_ssid);
  10.610 -    }
  10.611 -
  10.612 -    write_unlock(&ssid_list_rwlock);
  10.613 -}
  10.614 -
  10.615 -
  10.616 -/*
  10.617 -   Check the list of domains whether either one of them uses a
  10.618 -   to-be-deleted ssidref.
  10.619 - */
  10.620 -static int
  10.621 -acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
  10.622 -                           struct acm_sized_buffer *errors)
  10.623 -{
  10.624 -    int rc = 0;
  10.625 -    uint idx;
  10.626 -    /* check for running domains that should not be there anymore */
  10.627 -    for ( idx = 0; idx < dels->num_items; idx++ )
  10.628 -    {
  10.629 -        if ( acm_check_used_ssidref(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  10.630 -                                    dels->array[idx],
  10.631 -                                    errors) > 0 ||
  10.632 -             acm_check_used_ssidref(ACM_CHINESE_WALL_POLICY,
  10.633 -                                    dels->array[idx],
  10.634 -                                    errors) > 0)
  10.635 -        {
  10.636 -            rc = ACM_ERROR;
  10.637 -            break;
  10.638 -        }
  10.639 -    }
  10.640 -    return rc;
  10.641 -}
  10.642 -
  10.643 -
  10.644 -/*
  10.645 - * Change the policy of the system.
  10.646 - */
  10.647 -int
  10.648 -acm_change_policy(struct acm_change_policy *chgpolicy)
  10.649 -{
  10.650 -    int rc = 0;
  10.651 -    u8 *binpolicy = NULL;
  10.652 -    struct acm_sized_buffer dels =
  10.653 -    {
  10.654 -        .array = NULL,
  10.655 -    };
  10.656 -    struct acm_sized_buffer ssidmap =
  10.657 -    {
  10.658 -        .array = NULL,
  10.659 -    };
  10.660 -    struct acm_sized_buffer errors =
  10.661 -    {
  10.662 -        .array = NULL,
  10.663 -    };
  10.664 -
  10.665 -    gdprintk(XENLOG_INFO, "change policy operation\n");
  10.666 -
  10.667 -    if ( (chgpolicy->delarray_size > 4096) ||
  10.668 -         (chgpolicy->chgarray_size > 4096) ||
  10.669 -         (chgpolicy->errarray_size > 4096))
  10.670 -    {
  10.671 -        return ACM_ERROR;
  10.672 -    }
  10.673 -
  10.674 -    dels.num_items = chgpolicy->delarray_size / sizeof(uint32_t);
  10.675 -    if ( dels.num_items > 0 )
  10.676 -    {
  10.677 -        dels.array = xmalloc_array(uint32_t, dels.num_items);
  10.678 -        if ( dels.array == NULL )
  10.679 -        {
  10.680 -            rc = -ENOMEM;
  10.681 -            goto acm_chg_policy_exit;
  10.682 -        }
  10.683 -    }
  10.684 -
  10.685 -    ssidmap.num_items = chgpolicy->chgarray_size / sizeof(uint32_t);
  10.686 -    if ( ssidmap.num_items > 0 )
  10.687 -    {
  10.688 -        ssidmap.array = xmalloc_array(uint32_t, ssidmap.num_items);
  10.689 -        if ( ssidmap.array == NULL )
  10.690 -        {
  10.691 -            rc = -ENOMEM;
  10.692 -            goto acm_chg_policy_exit;
  10.693 -        }
  10.694 -    }
  10.695 -
  10.696 -    errors.num_items = chgpolicy->errarray_size / sizeof(uint32_t);
  10.697 -    if ( errors.num_items > 0 )
  10.698 -    {
  10.699 -        errors.array = xmalloc_array(uint32_t, errors.num_items);
  10.700 -        if ( errors.array == NULL )
  10.701 -        {
  10.702 -            rc = -ENOMEM;
  10.703 -            goto acm_chg_policy_exit;
  10.704 -        }
  10.705 -        memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
  10.706 -    }
  10.707 -
  10.708 -    binpolicy = xmalloc_array(u8,
  10.709 -                              chgpolicy->policy_pushcache_size);
  10.710 -    if ( binpolicy == NULL )
  10.711 -    {
  10.712 -        rc = -ENOMEM;
  10.713 -        goto acm_chg_policy_exit;
  10.714 -    }
  10.715 -
  10.716 -    if ( copy_from_guest(dels.array,
  10.717 -                         chgpolicy->del_array,
  10.718 -                         dels.num_items) ||
  10.719 -         copy_from_guest(ssidmap.array,
  10.720 -                         chgpolicy->chg_array,
  10.721 -                         ssidmap.num_items) ||
  10.722 -         copy_from_guest(binpolicy,
  10.723 -                         chgpolicy->policy_pushcache,
  10.724 -                         chgpolicy->policy_pushcache_size ))
  10.725 -    {
  10.726 -        rc = -EFAULT;
  10.727 -        goto acm_chg_policy_exit;
  10.728 -    }
  10.729 -
  10.730 -    rc = do_acm_set_policy(binpolicy,
  10.731 -                           chgpolicy->policy_pushcache_size,
  10.732 -                           0,
  10.733 -                           &dels, &ssidmap, &errors);
  10.734 -
  10.735 -    if ( (errors.num_items > 0) &&
  10.736 -         copy_to_guest(chgpolicy->err_array,
  10.737 -                       errors.array,
  10.738 -                       errors.num_items ) )
  10.739 -    {
  10.740 -        rc = -EFAULT;
  10.741 -        goto acm_chg_policy_exit;
  10.742 -    }
  10.743 -
  10.744 -
  10.745 -acm_chg_policy_exit:
  10.746 -    xfree(dels.array);
  10.747 -    xfree(ssidmap.array);
  10.748 -    xfree(errors.array);
  10.749 -    xfree(binpolicy);
  10.750 -
  10.751 -    return rc;
  10.752 -}
  10.753 -
  10.754 -
  10.755 -/*
  10.756 - * Lookup the new ssidref given the domain's id.
  10.757 - * The translation map provides a list of tuples in the format
  10.758 - * (domid, new ssidref).
  10.759 - */
  10.760 -static ssidref_t
  10.761 -domid_to_newssid(const struct acm_ssid_domain *rawssid,
  10.762 -                 const struct acm_sized_buffer *map)
  10.763 -{
  10.764 -    domid_t domid = rawssid->domainid;
  10.765 -    uint i;
  10.766 -    for ( i = 0; (i+1) < map->num_items; i += 2 )
  10.767 -    {
  10.768 -        if ( map->array[i] == domid )
  10.769 -            return (ssidref_t)map->array[i+1];
  10.770 -    }
  10.771 -    return ACM_INVALID_SSIDREF;
  10.772 -}
  10.773 -
  10.774 -
  10.775 -int
  10.776 -do_acm_relabel_doms(struct acm_sized_buffer *relabel_map,
  10.777 -                    struct acm_sized_buffer *errors)
  10.778 -{
  10.779 -    int rc = 0, irc;
  10.780 -
  10.781 -    write_lock(&acm_bin_pol_rwlock);
  10.782 -
  10.783 -    acm_doms_change_ssidref(domid_to_newssid, relabel_map);
  10.784 -
  10.785 -    /* run tests; collect as much error info as possible */
  10.786 -    irc =  do_chwall_init_state_curr(errors);
  10.787 -    irc += do_ste_init_state_curr(errors);
  10.788 -    if ( irc != 0 )
  10.789 -    {
  10.790 -        rc = -EFAULT;
  10.791 -        goto acm_relabel_doms_lock_err_exit;
  10.792 -    }
  10.793 -
  10.794 -    write_unlock(&acm_bin_pol_rwlock);
  10.795 -
  10.796 -    return rc;
  10.797 -
  10.798 -acm_relabel_doms_lock_err_exit:
  10.799 -    /* revert the new ssidref assignment */
  10.800 -    acm_doms_restore_ssidref();
  10.801 -    do_chwall_init_state_curr(NULL);
  10.802 -
  10.803 -    write_unlock(&acm_bin_pol_rwlock);
  10.804 -
  10.805 -    return rc;
  10.806 -}
  10.807 -
  10.808 -
  10.809 -int
  10.810 -acm_relabel_domains(struct acm_relabel_doms *relabel)
  10.811 -{
  10.812 -    int rc = ACM_OK;
  10.813 -    struct acm_sized_buffer relabels =
  10.814 -    {
  10.815 -        .array = NULL,
  10.816 -    };
  10.817 -    struct acm_sized_buffer errors =
  10.818 -    {
  10.819 -        .array = NULL,
  10.820 -    };
  10.821 -
  10.822 -    if ( relabel->relabel_map_size > 4096 )
  10.823 -    {
  10.824 -        return ACM_ERROR;
  10.825 -    }
  10.826 -
  10.827 -    relabels.num_items = relabel->relabel_map_size / sizeof(uint32_t);
  10.828 -    if ( relabels.num_items > 0 )
  10.829 -    {
  10.830 -        relabels.array = xmalloc_array(uint32_t, relabels.num_items);
  10.831 -        if ( relabels.array == NULL )
  10.832 -        {
  10.833 -            rc = -ENOMEM;
  10.834 -            goto acm_relabel_doms_exit;
  10.835 -        }
  10.836 -    }
  10.837 -
  10.838 -    errors.num_items = relabel->errarray_size / sizeof(uint32_t);
  10.839 -    if ( errors.num_items > 0 )
  10.840 -    {
  10.841 -        errors.array = xmalloc_array(uint32_t, errors.num_items);
  10.842 -        if ( errors.array == NULL )
  10.843 -        {
  10.844 -            rc = -ENOMEM;
  10.845 -            goto acm_relabel_doms_exit;
  10.846 -        }
  10.847 -        memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
  10.848 -    }
  10.849 -
  10.850 -    if ( copy_from_guest(relabels.array,
  10.851 -                         relabel->relabel_map,
  10.852 -                         relabels.num_items) )
  10.853 -    {
  10.854 -        rc = -EFAULT;
  10.855 -        goto acm_relabel_doms_exit;
  10.856 -    }
  10.857 -
  10.858 -    rc = do_acm_relabel_doms(&relabels, &errors);
  10.859 -
  10.860 -    if ( copy_to_guest(relabel->err_array,
  10.861 -                       errors.array,
  10.862 -                       errors.num_items ) )
  10.863 -        rc = -EFAULT;
  10.864 -
  10.865 -acm_relabel_doms_exit:
  10.866 -    xfree(relabels.array);
  10.867 -    xfree(errors.array);
  10.868 -    return rc;
  10.869 -}
  10.870 -
  10.871 -/*
  10.872 - * Local variables:
  10.873 - * mode: C
  10.874 - * c-set-style: "BSD"
  10.875 - * c-basic-offset: 4
  10.876 - * tab-width: 4
  10.877 - * indent-tabs-mode: nil
  10.878 - * End:
  10.879 - */
    11.1 --- a/xen/acm/acm_simple_type_enforcement_hooks.c	Fri Aug 31 11:37:20 2007 +0100
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,914 +0,0 @@
    11.4 -/****************************************************************
    11.5 - * acm_simple_type_enforcement_hooks.c
    11.6 - * 
    11.7 - * Copyright (C) 2005 IBM Corporation
    11.8 - *
    11.9 - * Author:
   11.10 - * Reiner Sailer <sailer@watson.ibm.com>
   11.11 - *
   11.12 - * Contributors:
   11.13 - * Stefan Berger <stefanb@watson.ibm.com>
   11.14 - *         support for network order binary policies
   11.15 - *
   11.16 - * This program is free software; you can redistribute it and/or
   11.17 - * modify it under the terms of the GNU General Public License as
   11.18 - * published by the Free Software Foundation, version 2 of the
   11.19 - * License.
   11.20 - *
   11.21 - * sHype Simple Type Enforcement for Xen
   11.22 - *     STE allows to control which domains can setup sharing
   11.23 - *     (eventchannels right now) with which other domains. Hooks
   11.24 - *     are defined and called throughout Xen when domains bind to
   11.25 - *     shared resources (setup eventchannels) and a domain is allowed
   11.26 - *     to setup sharing with another domain if and only if both domains
   11.27 - *     share at least on common type.
   11.28 - *
   11.29 - */
   11.30 -
   11.31 -#include <xen/lib.h>
   11.32 -#include <asm/types.h>
   11.33 -#include <asm/current.h>
   11.34 -#include <acm/acm_hooks.h>
   11.35 -#include <asm/atomic.h>
   11.36 -#include <acm/acm_endian.h>
   11.37 -#include <acm/acm_core.h>
   11.38 -
   11.39 -ssidref_t dom0_ste_ssidref = 0x0001;
   11.40 -
   11.41 -/* local cache structures for STE policy */
   11.42 -struct ste_binary_policy ste_bin_pol;
   11.43 -
   11.44 -static inline int have_common_type (ssidref_t ref1, ssidref_t ref2)
   11.45 -{
   11.46 -    int i;
   11.47 -
   11.48 -    if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
   11.49 -         ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
   11.50 -    {
   11.51 -        for( i = 0; i< ste_bin_pol.max_types; i++ )
   11.52 -            if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
   11.53 -                 ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
   11.54 -            {
   11.55 -                printkd("%s: common type #%02x.\n", __func__, i);
   11.56 -                return 1;
   11.57 -            }
   11.58 -    }
   11.59 -    return 0;
   11.60 -}
   11.61 -
   11.62 -static inline int is_superset(ssidref_t ref1, ssidref_t ref2)
   11.63 -{
   11.64 -    int i;
   11.65 -
   11.66 -    if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
   11.67 -         ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
   11.68 -    {
   11.69 -        for( i = 0; i< ste_bin_pol.max_types; i++ )
   11.70 -            if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
   11.71 -                 ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
   11.72 -            {
   11.73 -                return 0;
   11.74 -            }
   11.75 -    } else {
   11.76 -        return 0;
   11.77 -    }
   11.78 -    return 1;
   11.79 -}
   11.80 -
   11.81 -
   11.82 -/* Helper function: return = (subj and obj share a common type) */
   11.83 -static int share_common_type(struct domain *subj, struct domain *obj)
   11.84 -{
   11.85 -    ssidref_t ref_s, ref_o;
   11.86 -    int ret;
   11.87 -
   11.88 -    if ( (subj == NULL) || (obj == NULL) ||
   11.89 -         (subj->ssid == NULL) || (obj->ssid == NULL) )
   11.90 -        return 0;
   11.91 -
   11.92 -    read_lock(&acm_bin_pol_rwlock);
   11.93 -
   11.94 -    /* lookup the policy-local ssids */
   11.95 -    ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
   11.96 -                       (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
   11.97 -    ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
   11.98 -                       (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
   11.99 -    /* check whether subj and obj share a common ste type */
  11.100 -    ret = have_common_type(ref_s, ref_o);
  11.101 -
  11.102 -    read_unlock(&acm_bin_pol_rwlock);
  11.103 -
  11.104 -    return ret;
  11.105 -}
  11.106 -
  11.107 -/*
  11.108 - * Initializing STE policy (will be filled by policy partition
  11.109 - * using setpolicy command)
  11.110 - */
  11.111 -int acm_init_ste_policy(void)
  11.112 -{
  11.113 -    /* minimal startup policy; policy write-locked already */
  11.114 -    ste_bin_pol.max_types = 1;
  11.115 -    ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref;
  11.116 -    ste_bin_pol.ssidrefs =
  11.117 -            (domaintype_t *)xmalloc_array(domaintype_t,
  11.118 -                                          ste_bin_pol.max_types *
  11.119 -                                          ste_bin_pol.max_ssidrefs);
  11.120 -
  11.121 -    if (ste_bin_pol.ssidrefs == NULL)
  11.122 -        return ACM_INIT_SSID_ERROR;
  11.123 -
  11.124 -    memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) *
  11.125 -                                    ste_bin_pol.max_types *
  11.126 -                                    ste_bin_pol.max_ssidrefs);
  11.127 -
  11.128 -    /* initialize state so that dom0 can start up and communicate with itself */
  11.129 -    ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1;
  11.130 -
  11.131 -    /* init stats */
  11.132 -    atomic_set(&(ste_bin_pol.ec_eval_count), 0);
  11.133 -    atomic_set(&(ste_bin_pol.ec_denied_count), 0);
  11.134 -    atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
  11.135 -    atomic_set(&(ste_bin_pol.gt_eval_count), 0);
  11.136 -    atomic_set(&(ste_bin_pol.gt_denied_count), 0);
  11.137 -    atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
  11.138 -
  11.139 -    return ACM_OK;
  11.140 -}
  11.141 -
  11.142 -
  11.143 -/* ste initialization function hooks */
  11.144 -static int
  11.145 -ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
  11.146 -{
  11.147 -    int i;
  11.148 -    struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
  11.149 -
  11.150 -    if ( ste_ssidp == NULL )
  11.151 -        return ACM_INIT_SSID_ERROR;
  11.152 -
  11.153 -    /* get policy-local ssid reference */
  11.154 -    ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  11.155 -                                         ssidref);
  11.156 -
  11.157 -    if ( (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) )
  11.158 -    {
  11.159 -        printkd("%s: ERROR ste_ssidref (%x) undefined or unset (0).\n",
  11.160 -                __func__, ste_ssidp->ste_ssidref);
  11.161 -        xfree(ste_ssidp);
  11.162 -        return ACM_INIT_SSID_ERROR;
  11.163 -    }
  11.164 -    /* clean ste cache */
  11.165 -    for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  11.166 -        ste_ssidp->ste_cache[i].valid = ACM_STE_free;
  11.167 -
  11.168 -    (*ste_ssid) = ste_ssidp;
  11.169 -    printkd("%s: determined ste_ssidref to %x.\n", 
  11.170 -            __func__, ste_ssidp->ste_ssidref);
  11.171 -
  11.172 -    return ACM_OK;
  11.173 -}
  11.174 -
  11.175 -
  11.176 -static void
  11.177 -ste_free_domain_ssid(void *ste_ssid)
  11.178 -{
  11.179 -    xfree(ste_ssid);
  11.180 -    return;
  11.181 -}
  11.182 -
  11.183 -/* dump type enforcement cache; policy read-locked already */
  11.184 -static int 
  11.185 -ste_dump_policy(u8 *buf, u32 buf_size) {
  11.186 -    struct acm_ste_policy_buffer *ste_buf =
  11.187 -                                  (struct acm_ste_policy_buffer *)buf;
  11.188 -    int ret = 0;
  11.189 -
  11.190 -    if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
  11.191 -        return -EINVAL;
  11.192 -
  11.193 -    ste_buf->ste_max_types = cpu_to_be32(ste_bin_pol.max_types);
  11.194 -    ste_buf->ste_max_ssidrefs = cpu_to_be32(ste_bin_pol.max_ssidrefs);
  11.195 -    ste_buf->policy_code = cpu_to_be32(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
  11.196 -    ste_buf->ste_ssid_offset =
  11.197 -                           cpu_to_be32(sizeof(struct acm_ste_policy_buffer));
  11.198 -    ret = be32_to_cpu(ste_buf->ste_ssid_offset) +
  11.199 -        sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
  11.200 -
  11.201 -    ret = (ret + 7) & ~7;
  11.202 -
  11.203 -    if (buf_size < ret)
  11.204 -        return -EINVAL;
  11.205 -
  11.206 -    /* now copy buffer over */
  11.207 -    arrcpy(buf + be32_to_cpu(ste_buf->ste_ssid_offset),
  11.208 -           ste_bin_pol.ssidrefs,
  11.209 -           sizeof(domaintype_t),
  11.210 -           ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
  11.211 -
  11.212 -    return ret;
  11.213 -}
  11.214 -
  11.215 -/*
  11.216 - * ste_init_state is called when a policy is changed to detect violations
  11.217 - * (return != 0). from a security point of view, we simulate that all
  11.218 - * running domains are re-started and all sharing decisions are replayed
  11.219 - * to detect violations or current sharing behavior (right now:
  11.220 - * event_channels, future: also grant_tables)
  11.221 - */ 
  11.222 -static int
  11.223 -ste_init_state(struct acm_sized_buffer *errors)
  11.224 -{
  11.225 -    int violation = 1;
  11.226 -    struct ste_ssid *ste_ssid, *ste_rssid;
  11.227 -    ssidref_t ste_ssidref, ste_rssidref;
  11.228 -    struct domain *d, *rdom;
  11.229 -    domid_t rdomid;
  11.230 -    struct active_grant_entry *act;
  11.231 -    int port, i;
  11.232 -
  11.233 -    rcu_read_lock(&domlist_read_lock);
  11.234 -    read_lock(&ssid_list_rwlock);
  11.235 -
  11.236 -    /* go through all domains and adjust policy as if this domain was
  11.237 -       started now */
  11.238 -
  11.239 -    for_each_domain ( d )
  11.240 -    {
  11.241 -        struct evtchn *ports;
  11.242 -        unsigned int bucket;
  11.243 -
  11.244 -        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
  11.245 -                             (struct acm_ssid_domain *)d->ssid);
  11.246 -        ste_ssidref = ste_ssid->ste_ssidref;
  11.247 -        traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
  11.248 -                    __func__, d->domain_id, ste_ssidref);
  11.249 -        /* a) check for event channel conflicts */
  11.250 -        for ( bucket = 0; bucket < NR_EVTCHN_BUCKETS; bucket++ )
  11.251 -        {
  11.252 -            spin_lock(&d->evtchn_lock);
  11.253 -            ports = d->evtchn[bucket];
  11.254 -            if ( ports == NULL)
  11.255 -            {
  11.256 -                spin_unlock(&d->evtchn_lock);
  11.257 -                break;
  11.258 -            }
  11.259 -
  11.260 -            for ( port = 0; port < EVTCHNS_PER_BUCKET; port++ )
  11.261 -            {
  11.262 -                if ( ports[port].state == ECS_INTERDOMAIN )
  11.263 -                {
  11.264 -                    rdom = ports[port].u.interdomain.remote_dom;
  11.265 -                    rdomid = rdom->domain_id;
  11.266 -                } else {
  11.267 -                    continue; /* port unused */
  11.268 -                }
  11.269 -
  11.270 -                /* rdom now has remote domain */
  11.271 -                ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  11.272 -                                      (struct acm_ssid_domain *)(rdom->ssid));
  11.273 -                ste_rssidref = ste_rssid->ste_ssidref;
  11.274 -                traceprintk("%s: eventch: domain %x (ssidref %x) --> "
  11.275 -                            "domain %x (rssidref %x) used (port %x).\n",
  11.276 -                            __func__, d->domain_id, ste_ssidref,
  11.277 -                            rdom->domain_id, ste_rssidref, port);
  11.278 -                /* check whether on subj->ssid, obj->ssid share a common type*/
  11.279 -                if ( ! have_common_type(ste_ssidref, ste_rssidref) )
  11.280 -                {
  11.281 -                    printkd("%s: Policy violation in event channel domain "
  11.282 -                            "%x -> domain %x.\n",
  11.283 -                            __func__, d->domain_id, rdomid);
  11.284 -                    spin_unlock(&d->evtchn_lock);
  11.285 -
  11.286 -                    acm_array_append_tuple(errors,
  11.287 -                                           ACM_EVTCHN_SHARING_VIOLATION,
  11.288 -                                           d->domain_id << 16 | rdomid);
  11.289 -                    goto out;
  11.290 -                }
  11.291 -            }
  11.292 -            spin_unlock(&d->evtchn_lock);
  11.293 -        } 
  11.294 -
  11.295 -
  11.296 -        /* b) check for grant table conflicts on shared pages */
  11.297 -        spin_lock(&d->grant_table->lock);
  11.298 -        for ( i = 0; i < nr_active_grant_frames(d->grant_table); i++ )
  11.299 -        {
  11.300 -#define APP (PAGE_SIZE / sizeof(struct active_grant_entry))
  11.301 -            act = &d->grant_table->active[i/APP][i%APP];
  11.302 -            if ( act->pin != 0 ) {
  11.303 -                printkd("%s: grant dom (%hu) SHARED (%d) pin (%d)  "
  11.304 -                        "dom:(%hu) frame:(%lx)\n",
  11.305 -                        __func__, d->domain_id, i, act->pin,
  11.306 -                        act->domid, (unsigned long)act->frame);
  11.307 -                rdomid = act->domid;
  11.308 -                if ( (rdom = rcu_lock_domain_by_id(rdomid)) == NULL )
  11.309 -                {
  11.310 -                    spin_unlock(&d->grant_table->lock);
  11.311 -                    printkd("%s: domain not found ERROR!\n", __func__);
  11.312 -
  11.313 -                    acm_array_append_tuple(errors,
  11.314 -                                           ACM_DOMAIN_LOOKUP,
  11.315 -                                           rdomid);
  11.316 -                    goto out;
  11.317 -                }
  11.318 -                /* rdom now has remote domain */
  11.319 -                ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  11.320 -                                      (struct acm_ssid_domain *)(rdom->ssid));
  11.321 -                ste_rssidref = ste_rssid->ste_ssidref;
  11.322 -                rcu_unlock_domain(rdom);
  11.323 -                if ( ! have_common_type(ste_ssidref, ste_rssidref) )
  11.324 -                {
  11.325 -                    spin_unlock(&d->grant_table->lock);
  11.326 -                    printkd("%s: Policy violation in grant table "
  11.327 -                            "sharing domain %x -> domain %x.\n",
  11.328 -                            __func__, d->domain_id, rdomid);
  11.329 -
  11.330 -                    acm_array_append_tuple(errors,
  11.331 -                                           ACM_GNTTAB_SHARING_VIOLATION,
  11.332 -                                           d->domain_id << 16 | rdomid);
  11.333 -                    goto out;
  11.334 -                }
  11.335 -            }
  11.336 -        }
  11.337 -        spin_unlock(&d->grant_table->lock);
  11.338 -    }
  11.339 -    violation = 0;
  11.340 - out:
  11.341 -    read_unlock(&ssid_list_rwlock);
  11.342 -    rcu_read_unlock(&domlist_read_lock);
  11.343 -    return violation;
  11.344 -    /*
  11.345 -       returning "violation != 0" means that existing sharing between domains
  11.346 -       would not have been allowed if the new policy had been enforced before
  11.347 -       the sharing; for ste, this means that there are at least 2 domains
  11.348 -       that have established sharing through event-channels or grant-tables
  11.349 -       but these two domains don't have no longer a common type in their
  11.350 -       typesets referenced by their ssidrefs
  11.351 -      */
  11.352 -}
  11.353 -
  11.354 -
  11.355 -/*
  11.356 - * Call ste_init_state with the current policy.
  11.357 - */
  11.358 -int
  11.359 -do_ste_init_state_curr(struct acm_sized_buffer *errors)
  11.360 -{
  11.361 -    return ste_init_state(errors);
  11.362 -}
  11.363 -
  11.364 -
  11.365 -/* set new policy; policy write-locked already */
  11.366 -static int
  11.367 -_ste_update_policy(u8 *buf, u32 buf_size, int test_only,
  11.368 -                   struct acm_sized_buffer *errors)
  11.369 -{
  11.370 -    int rc = -EFAULT;
  11.371 -    struct acm_ste_policy_buffer *ste_buf =
  11.372 -                                 (struct acm_ste_policy_buffer *)buf;
  11.373 -    void *ssidrefsbuf;
  11.374 -    struct ste_ssid *ste_ssid;
  11.375 -    struct acm_ssid_domain *rawssid;
  11.376 -    int i;
  11.377 -
  11.378 -
  11.379 -    /* 1. create and copy-in new ssidrefs buffer */
  11.380 -    ssidrefsbuf = xmalloc_array(u8,
  11.381 -                                sizeof(domaintype_t) *
  11.382 -                                 ste_buf->ste_max_types *
  11.383 -                                 ste_buf->ste_max_ssidrefs);
  11.384 -    if ( ssidrefsbuf == NULL ) {
  11.385 -        return -ENOMEM;
  11.386 -    }
  11.387 -    if ( ste_buf->ste_ssid_offset +
  11.388 -         sizeof(domaintype_t) *
  11.389 -         ste_buf->ste_max_ssidrefs *
  11.390 -         ste_buf->ste_max_types > buf_size )
  11.391 -        goto error_free;
  11.392 -
  11.393 -    arrcpy(ssidrefsbuf, 
  11.394 -           buf + ste_buf->ste_ssid_offset,
  11.395 -           sizeof(domaintype_t),
  11.396 -           ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
  11.397 -
  11.398 -
  11.399 -    /*
  11.400 -     * 3. in test mode: re-calculate sharing decisions based on running
  11.401 -     *    domains; this can fail if new policy is conflicting with sharing
  11.402 -     *    of running domains
  11.403 -     *    now: reject violating new policy; future: adjust sharing through
  11.404 -     *    revoking sharing
  11.405 -     */
  11.406 -
  11.407 -    if ( test_only ) {
  11.408 -        /* temporarily replace old policy with new one for the testing */
  11.409 -        struct ste_binary_policy orig_ste_bin_pol = ste_bin_pol;
  11.410 -        ste_bin_pol.max_types = ste_buf->ste_max_types;
  11.411 -        ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
  11.412 -        ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
  11.413 -
  11.414 -        if ( ste_init_state(errors) )
  11.415 -        {
  11.416 -            /* new policy conflicts with sharing of running domains */
  11.417 -            printk("%s: New policy conflicts with running domains. "
  11.418 -                   "Policy load aborted.\n", __func__);
  11.419 -        } else {
  11.420 -            rc = ACM_OK;
  11.421 -        }
  11.422 -        /* revert changes, no matter whether testing was successful or not */
  11.423 -        ste_bin_pol = orig_ste_bin_pol;
  11.424 -        goto error_free;
  11.425 -    }
  11.426 -
  11.427 -    /* 3. replace old policy (activate new policy) */
  11.428 -    ste_bin_pol.max_types = ste_buf->ste_max_types;
  11.429 -    ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
  11.430 -    xfree(ste_bin_pol.ssidrefs);
  11.431 -    ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
  11.432 -
  11.433 -    /* clear all ste caches */
  11.434 -    read_lock(&ssid_list_rwlock);
  11.435 -
  11.436 -    for_each_acmssid( rawssid )
  11.437 -    {
  11.438 -        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
  11.439 -        for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  11.440 -            ste_ssid->ste_cache[i].valid = ACM_STE_free;
  11.441 -    }
  11.442 -
  11.443 -    read_unlock(&ssid_list_rwlock);
  11.444 -
  11.445 -    return ACM_OK;
  11.446 -
  11.447 - error_free:
  11.448 -    if ( !test_only )
  11.449 -        printk("%s: ERROR setting policy.\n", __func__);
  11.450 -    xfree(ssidrefsbuf);
  11.451 -    return rc;
  11.452 -}
  11.453 -
  11.454 -static int
  11.455 -ste_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
  11.456 -                struct acm_sized_buffer *errors)
  11.457 -{
  11.458 -    struct acm_ste_policy_buffer *ste_buf =
  11.459 -             (struct acm_ste_policy_buffer *)buf;
  11.460 -
  11.461 -    if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
  11.462 -        return -EINVAL;
  11.463 -
  11.464 -    /* Convert endianess of policy */
  11.465 -    ste_buf->policy_code = be32_to_cpu(ste_buf->policy_code);
  11.466 -    ste_buf->policy_version = be32_to_cpu(ste_buf->policy_version);
  11.467 -    ste_buf->ste_max_types = be32_to_cpu(ste_buf->ste_max_types);
  11.468 -    ste_buf->ste_max_ssidrefs = be32_to_cpu(ste_buf->ste_max_ssidrefs);
  11.469 -    ste_buf->ste_ssid_offset = be32_to_cpu(ste_buf->ste_ssid_offset);
  11.470 -
  11.471 -    /* policy type and version checks */
  11.472 -    if ( (ste_buf->policy_code != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ||
  11.473 -         (ste_buf->policy_version != ACM_STE_VERSION) )
  11.474 -        return -EINVAL;
  11.475 -
  11.476 -    /* during boot dom0_chwall_ssidref is set */
  11.477 -    if ( is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs) )
  11.478 -        return -EINVAL;
  11.479 -
  11.480 -    return _ste_update_policy(buf, buf_size, 1, errors);
  11.481 -}
  11.482 -
  11.483 -static int
  11.484 -ste_set_policy(u8 *buf, u32 buf_size)
  11.485 -{
  11.486 -    return _ste_update_policy(buf, buf_size, 0, NULL);
  11.487 -}
  11.488 -
  11.489 -static int 
  11.490 -ste_dump_stats(u8 *buf, u16 buf_len)
  11.491 -{
  11.492 -    struct acm_ste_stats_buffer stats;
  11.493 -
  11.494 -    /* now send the hook counts to user space */
  11.495 -    stats.ec_eval_count =
  11.496 -                    cpu_to_be32(atomic_read(&ste_bin_pol.ec_eval_count));
  11.497 -    stats.gt_eval_count =
  11.498 -                    cpu_to_be32(atomic_read(&ste_bin_pol.gt_eval_count));
  11.499 -    stats.ec_denied_count =
  11.500 -                    cpu_to_be32(atomic_read(&ste_bin_pol.ec_denied_count));
  11.501 -    stats.gt_denied_count =
  11.502 -                    cpu_to_be32(atomic_read(&ste_bin_pol.gt_denied_count));
  11.503 -    stats.ec_cachehit_count =
  11.504 -                    cpu_to_be32(atomic_read(&ste_bin_pol.ec_cachehit_count));
  11.505 -    stats.gt_cachehit_count =
  11.506 -                    cpu_to_be32(atomic_read(&ste_bin_pol.gt_cachehit_count));
  11.507 -
  11.508 -    if ( buf_len < sizeof(struct acm_ste_stats_buffer) )
  11.509 -        return -ENOMEM;
  11.510 -
  11.511 -    memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
  11.512 -
  11.513 -    return sizeof(struct acm_ste_stats_buffer);
  11.514 -}
  11.515 -
  11.516 -static int
  11.517 -ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
  11.518 -{
  11.519 -    int i;
  11.520 -
  11.521 -    /* fill in buffer */
  11.522 -    if ( ste_bin_pol.max_types > len )
  11.523 -        return -EFAULT;
  11.524 -
  11.525 -    if ( ssidref >= ste_bin_pol.max_ssidrefs )
  11.526 -        return -EFAULT;
  11.527 -
  11.528 -    /* read types for chwall ssidref */
  11.529 -    for( i = 0; i< ste_bin_pol.max_types; i++ )
  11.530 -    {
  11.531 -        if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
  11.532 -            buf[i] = 1;
  11.533 -        else
  11.534 -            buf[i] = 0;
  11.535 -    }
  11.536 -    return ste_bin_pol.max_types;
  11.537 -}
  11.538 -
  11.539 -/* we need to go through this before calling the hooks,
  11.540 - * returns 1 == cache hit */
  11.541 -static int inline
  11.542 -check_cache(struct domain *dom, domid_t rdom)
  11.543 -{
  11.544 -    struct ste_ssid *ste_ssid;
  11.545 -    int i;
  11.546 -
  11.547 -    printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
  11.548 -
  11.549 -    if (dom->ssid == NULL)
  11.550 -        return 0;
  11.551 -    ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
  11.552 -                         (struct acm_ssid_domain *)(dom->ssid));
  11.553 -
  11.554 -    for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  11.555 -    {
  11.556 -        if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
  11.557 -             (ste_ssid->ste_cache[i].id == rdom) )
  11.558 -        {
  11.559 -            printkd("cache hit (entry %x, id= %x!\n",
  11.560 -                    i,
  11.561 -                    ste_ssid->ste_cache[i].id);
  11.562 -            return 1;
  11.563 -        }
  11.564 -    }
  11.565 -    return 0;
  11.566 -}
  11.567 -
  11.568 -
  11.569 -/* we only get here if there is NO entry yet; no duplication check! */
  11.570 -static void inline
  11.571 -cache_result(struct domain *subj, struct domain *obj) {
  11.572 -    struct ste_ssid *ste_ssid;
  11.573 -    int i;
  11.574 -
  11.575 -    printkd("caching from doms: %x --> %x.\n",
  11.576 -            subj->domain_id, obj->domain_id);
  11.577 -
  11.578 -    if ( subj->ssid == NULL )
  11.579 -        return;
  11.580 -
  11.581 -    ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
  11.582 -                         (struct acm_ssid_domain *)(subj)->ssid);
  11.583 -
  11.584 -    for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  11.585 -        if ( ste_ssid->ste_cache[i].valid == ACM_STE_free )
  11.586 -            break;
  11.587 -    if ( i < ACM_TE_CACHE_SIZE )
  11.588 -    {
  11.589 -        ste_ssid->ste_cache[i].valid = ACM_STE_valid;
  11.590 -        ste_ssid->ste_cache[i].id = obj->domain_id;
  11.591 -    } else
  11.592 -        printk ("Cache of dom %x is full!\n", subj->domain_id);
  11.593 -}
  11.594 -
  11.595 -/* deletes entries for domain 'id' from all caches (re-use) */
  11.596 -static void inline
  11.597 -clean_id_from_cache(domid_t id) 
  11.598 -{
  11.599 -    struct ste_ssid *ste_ssid;
  11.600 -    int i;
  11.601 -    struct acm_ssid_domain *rawssid;
  11.602 -
  11.603 -    printkd("deleting cache for dom %x.\n", id);
  11.604 -
  11.605 -    read_lock(&ssid_list_rwlock);
  11.606 -    /* look through caches of all domains */
  11.607 -
  11.608 -    for_each_acmssid ( rawssid )
  11.609 -    {
  11.610 -        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
  11.611 -
  11.612 -        if ( !ste_ssid )
  11.613 -        {
  11.614 -            printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n",
  11.615 -                   __func__);
  11.616 -            goto out;
  11.617 -        }
  11.618 -        for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  11.619 -            if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
  11.620 -                 (ste_ssid->ste_cache[i].id == id) )
  11.621 -                ste_ssid->ste_cache[i].valid = ACM_STE_free;
  11.622 -    }
  11.623 -
  11.624 - out:
  11.625 -    read_unlock(&ssid_list_rwlock);
  11.626 -}
  11.627 -
  11.628 -/***************************
  11.629 - * Authorization functions
  11.630 - **************************/
  11.631 -static int 
  11.632 -ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
  11.633 -{      
  11.634 -    /* check for ssidref in range for policy */
  11.635 -    ssidref_t ste_ssidref;
  11.636 -
  11.637 -    traceprintk("%s.\n", __func__);
  11.638 -
  11.639 -    read_lock(&acm_bin_pol_rwlock);
  11.640 -
  11.641 -    ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
  11.642 -
  11.643 -    if ( ste_ssidref >= ste_bin_pol.max_ssidrefs )
  11.644 -    {
  11.645 -        printk("%s: ERROR ste_ssidref > max(%x).\n", 
  11.646 -               __func__, ste_bin_pol.max_ssidrefs-1);
  11.647 -        read_unlock(&acm_bin_pol_rwlock);
  11.648 -        return ACM_ACCESS_DENIED;
  11.649 -    }
  11.650 -
  11.651 -    read_unlock(&acm_bin_pol_rwlock);
  11.652 -
  11.653 -    return ACM_ACCESS_PERMITTED;
  11.654 -}
  11.655 -
  11.656 -static int
  11.657 -ste_domain_create(void *subject_ssid, ssidref_t ssidref, domid_t  domid)
  11.658 -{
  11.659 -    return ste_pre_domain_create(subject_ssid, ssidref);
  11.660 -}
  11.661 -
  11.662 -
  11.663 -static void 
  11.664 -ste_domain_destroy(void *subject_ssid, struct domain *d)
  11.665 -{
  11.666 -    /* clean all cache entries for destroyed domain (might be re-used) */
  11.667 -    clean_id_from_cache(d->domain_id);
  11.668 -}
  11.669 -
  11.670 -/* -------- EVENTCHANNEL OPERATIONS -----------*/
  11.671 -static int
  11.672 -ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) {
  11.673 -    struct domain *subj, *obj;
  11.674 -    int ret;
  11.675 -    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  11.676 -                (id1 == DOMID_SELF) ? current->domain->domain_id : id1,
  11.677 -                (id2 == DOMID_SELF) ? current->domain->domain_id : id2);
  11.678 -
  11.679 -    if ( id1 == DOMID_SELF )
  11.680 -        id1 = current->domain->domain_id;
  11.681 -    if ( id2 == DOMID_SELF )
  11.682 -        id2 = current->domain->domain_id;
  11.683 -
  11.684 -    subj = rcu_lock_domain_by_id(id1);
  11.685 -    obj  = rcu_lock_domain_by_id(id2);
  11.686 -    if ( (subj == NULL) || (obj == NULL) )
  11.687 -    {
  11.688 -        ret = ACM_ACCESS_DENIED;
  11.689 -        goto out;
  11.690 -    }
  11.691 -    /* cache check late */
  11.692 -    if ( check_cache(subj, obj->domain_id) )
  11.693 -    {
  11.694 -        atomic_inc(&ste_bin_pol.ec_cachehit_count);
  11.695 -        ret = ACM_ACCESS_PERMITTED;
  11.696 -        goto out;
  11.697 -    }
  11.698 -    atomic_inc(&ste_bin_pol.ec_eval_count);
  11.699 -
  11.700 -    if ( share_common_type(subj, obj) )
  11.701 -    {
  11.702 -        cache_result(subj, obj);
  11.703 -        ret = ACM_ACCESS_PERMITTED;
  11.704 -    }
  11.705 -    else
  11.706 -    {
  11.707 -        atomic_inc(&ste_bin_pol.ec_denied_count);
  11.708 -        ret = ACM_ACCESS_DENIED;
  11.709 -    }
  11.710 -
  11.711 -  out:
  11.712 -    if ( obj != NULL )
  11.713 -        rcu_unlock_domain(obj);
  11.714 -    if ( subj != NULL )
  11.715 -        rcu_unlock_domain(subj);
  11.716 -    return ret;
  11.717 -}
  11.718 -
  11.719 -static int
  11.720 -ste_pre_eventchannel_interdomain(domid_t id)
  11.721 -{
  11.722 -    struct domain *subj=NULL, *obj=NULL;
  11.723 -    int ret;
  11.724 -
  11.725 -    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  11.726 -                current->domain->domain_id,
  11.727 -                (id == DOMID_SELF) ? current->domain->domain_id : id);
  11.728 -
  11.729 -    /* following is a bit longer but ensures that we
  11.730 -     * "put" only domains that we where "find"-ing 
  11.731 -     */
  11.732 -    if ( id == DOMID_SELF )
  11.733 -        id = current->domain->domain_id;
  11.734 -
  11.735 -    subj = current->domain;
  11.736 -    obj  = rcu_lock_domain_by_id(id);
  11.737 -    if ( obj == NULL )
  11.738 -    {
  11.739 -        ret = ACM_ACCESS_DENIED;
  11.740 -        goto out;
  11.741 -    }
  11.742 -
  11.743 -    /* cache check late, but evtchn is not on performance critical path */
  11.744 -    if ( check_cache(subj, obj->domain_id) )
  11.745 -    {
  11.746 -        atomic_inc(&ste_bin_pol.ec_cachehit_count);
  11.747 -        ret = ACM_ACCESS_PERMITTED;
  11.748 -        goto out;
  11.749 -    }
  11.750 -
  11.751 -    atomic_inc(&ste_bin_pol.ec_eval_count);
  11.752 -
  11.753 -    if ( share_common_type(subj, obj) )
  11.754 -    {
  11.755 -        cache_result(subj, obj);
  11.756 -        ret = ACM_ACCESS_PERMITTED;
  11.757 -    }
  11.758 -    else
  11.759 -    {
  11.760 -        atomic_inc(&ste_bin_pol.ec_denied_count);
  11.761 -        ret = ACM_ACCESS_DENIED;
  11.762 -    }
  11.763 -
  11.764 - out:
  11.765 -    if ( obj != NULL )
  11.766 -        rcu_unlock_domain(obj);
  11.767 -    return ret;
  11.768 -}
  11.769 -
  11.770 -/* -------- SHARED MEMORY OPERATIONS -----------*/
  11.771 -
  11.772 -static int
  11.773 -ste_pre_grant_map_ref (domid_t id)
  11.774 -{
  11.775 -    struct domain *obj, *subj;
  11.776 -    int ret;
  11.777 -    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  11.778 -                current->domain->domain_id, id);
  11.779 -
  11.780 -    if ( check_cache(current->domain, id) )
  11.781 -    {
  11.782 -        atomic_inc(&ste_bin_pol.gt_cachehit_count);
  11.783 -        return ACM_ACCESS_PERMITTED;
  11.784 -    }
  11.785 -    atomic_inc(&ste_bin_pol.gt_eval_count);
  11.786 -    subj = current->domain;
  11.787 -    obj = rcu_lock_domain_by_id(id);
  11.788 -
  11.789 -    if ( share_common_type(subj, obj) )
  11.790 -    {
  11.791 -        cache_result(subj, obj);
  11.792 -        ret = ACM_ACCESS_PERMITTED;
  11.793 -    }
  11.794 -    else
  11.795 -    {
  11.796 -        atomic_inc(&ste_bin_pol.gt_denied_count);
  11.797 -        printkd("%s: ACCESS DENIED!\n", __func__);
  11.798 -        ret = ACM_ACCESS_DENIED;
  11.799 -    }
  11.800 -    if ( obj != NULL )
  11.801 -        rcu_unlock_domain(obj);
  11.802 -    return ret;
  11.803 -}
  11.804 -
  11.805 -
  11.806 -/* since setting up grant tables involves some implicit information
  11.807 -   flow from the creating domain to the domain that is setup, we 
  11.808 -   check types in addition to the general authorization */
  11.809 -static int
  11.810 -ste_pre_grant_setup (domid_t id)
  11.811 -{
  11.812 -    struct domain *obj, *subj;
  11.813 -    int ret;
  11.814 -    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  11.815 -                current->domain->domain_id, id);
  11.816 -
  11.817 -    if ( check_cache(current->domain, id) )
  11.818 -    {
  11.819 -        atomic_inc(&ste_bin_pol.gt_cachehit_count);
  11.820 -        return ACM_ACCESS_PERMITTED;
  11.821 -    }
  11.822 -    atomic_inc(&ste_bin_pol.gt_eval_count);
  11.823 -    /* a) check authorization (eventually use specific capabilities) */
  11.824 -    if ( !IS_PRIV(current->domain) )
  11.825 -    {
  11.826 -        printk("%s: Grant table management authorization denied ERROR!\n",
  11.827 -               __func__);
  11.828 -        return ACM_ACCESS_DENIED;
  11.829 -    }
  11.830 -    /* b) check types */
  11.831 -    subj = current->domain;
  11.832 -    obj = rcu_lock_domain_by_id(id);
  11.833 -
  11.834 -    if ( share_common_type(subj, obj) )
  11.835 -    {
  11.836 -        cache_result(subj, obj);
  11.837 -        ret = ACM_ACCESS_PERMITTED;
  11.838 -    }
  11.839 -    else
  11.840 -    {
  11.841 -        atomic_inc(&ste_bin_pol.gt_denied_count);
  11.842 -        ret = ACM_ACCESS_DENIED;
  11.843 -    }
  11.844 -    if ( obj != NULL )
  11.845 -        rcu_unlock_domain(obj);
  11.846 -    return ret;
  11.847 -}
  11.848 -
  11.849 -/* -------- DOMAIN-Requested Decision hooks -----------*/
  11.850 -
  11.851 -static int
  11.852 -ste_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
  11.853 -{
  11.854 -    int hct = have_common_type(
  11.855 -        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
  11.856 -        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
  11.857 -    return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
  11.858 -}
  11.859 -
  11.860 -static int
  11.861 -ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
  11.862 -{
  11.863 -    int iss = is_superset(
  11.864 -        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
  11.865 -        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
  11.866 -    return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
  11.867 -}
  11.868 -
  11.869 -static int
  11.870 -ste_is_default_policy(void)
  11.871 -{
  11.872 -    return ((ste_bin_pol.max_types    == 1) &&
  11.873 -            (ste_bin_pol.max_ssidrefs == 2));
  11.874 -}
  11.875 -
  11.876 -/* now define the hook structure similarly to LSM */
  11.877 -struct acm_operations acm_simple_type_enforcement_ops = {
  11.878 -
  11.879 -    /* policy management services */
  11.880 -    .init_domain_ssid       = ste_init_domain_ssid,
  11.881 -    .free_domain_ssid       = ste_free_domain_ssid,
  11.882 -    .dump_binary_policy     = ste_dump_policy,
  11.883 -    .test_binary_policy     = ste_test_policy,
  11.884 -    .set_binary_policy      = ste_set_policy,
  11.885 -    .dump_statistics        = ste_dump_stats,
  11.886 -    .dump_ssid_types        = ste_dump_ssid_types,
  11.887 -
  11.888 -    /* domain management control hooks */
  11.889 -    .domain_create          = ste_domain_create,
  11.890 -    .domain_destroy         = ste_domain_destroy,
  11.891 -
  11.892 -    /* event channel control hooks */
  11.893 -    .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
  11.894 -    .fail_eventchannel_unbound = NULL,
  11.895 -    .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
  11.896 -    .fail_eventchannel_interdomain = NULL,
  11.897 -
  11.898 -    /* grant table control hooks */
  11.899 -    .pre_grant_map_ref      = ste_pre_grant_map_ref,
  11.900 -    .fail_grant_map_ref     = NULL,
  11.901 -    .pre_grant_setup        = ste_pre_grant_setup,
  11.902 -    .fail_grant_setup       = NULL,
  11.903 -    .sharing                = ste_sharing,
  11.904 -    .authorization          = ste_authorization,
  11.905 -
  11.906 -    .is_default_policy      = ste_is_default_policy,
  11.907 -};
  11.908 -
  11.909 -/*
  11.910 - * Local variables:
  11.911 - * mode: C
  11.912 - * c-set-style: "BSD"
  11.913 - * c-basic-offset: 4
  11.914 - * tab-width: 4
  11.915 - * indent-tabs-mode: nil
  11.916 - * End:
  11.917 - */
    12.1 --- a/xen/arch/x86/setup.c	Fri Aug 31 11:37:20 2007 +0100
    12.2 +++ b/xen/arch/x86/setup.c	Fri Aug 31 11:41:49 2007 +0100
    12.3 @@ -220,40 +220,6 @@ static void __init percpu_init_areas(voi
    12.4  #endif
    12.5  }
    12.6  
    12.7 -/* Fetch acm policy module from multiboot modules. */
    12.8 -static void __init extract_acm_policy(
    12.9 -    multiboot_info_t *mbi,
   12.10 -    unsigned int *initrdidx,
   12.11 -    char **_policy_start,
   12.12 -    unsigned long *_policy_len)
   12.13 -{
   12.14 -    int i;
   12.15 -    module_t *mod = (module_t *)__va(mbi->mods_addr);
   12.16 -    unsigned long start, policy_len;
   12.17 -    char *policy_start;
   12.18 -
   12.19 -    /*
   12.20 -     * Try all modules and see whichever could be the binary policy.
   12.21 -     * Adjust the initrdidx if module[1] is the binary policy.
   12.22 -     */
   12.23 -    for ( i = mbi->mods_count-1; i >= 1; i-- )
   12.24 -    {
   12.25 -        start = initial_images_start + (mod[i].mod_start-mod[0].mod_start);
   12.26 -        policy_start = maddr_to_bootstrap_virt(start);
   12.27 -        policy_len   = mod[i].mod_end - mod[i].mod_start;
   12.28 -        if ( acm_is_policy(policy_start, policy_len) )
   12.29 -        {
   12.30 -            printk("Policy len  0x%lx, start at %p - module %d.\n",
   12.31 -                   policy_len, policy_start, i);
   12.32 -            *_policy_start = policy_start;
   12.33 -            *_policy_len = policy_len;
   12.34 -            if ( i == 1 )
   12.35 -                *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
   12.36 -            break;
   12.37 -        }
   12.38 -    }
   12.39 -}
   12.40 -
   12.41  static void __init init_idle_domain(void)
   12.42  {
   12.43      struct domain *idle_domain;
   12.44 @@ -448,8 +414,6 @@ void __init __start_xen(unsigned long mb
   12.45      char *cmdline, *kextra;
   12.46      unsigned long _initrd_start = 0, _initrd_len = 0;
   12.47      unsigned int initrdidx = 1;
   12.48 -    char *_policy_start = NULL;
   12.49 -    unsigned long _policy_len = 0;
   12.50      multiboot_info_t *mbi = __va(mbi_p);
   12.51      module_t *mod = (module_t *)__va(mbi->mods_addr);
   12.52      unsigned long nr_pages, modules_length;
   12.53 @@ -1032,12 +996,6 @@ void __init __start_xen(unsigned long mb
   12.54      if ( opt_watchdog ) 
   12.55          watchdog_enable();
   12.56  
   12.57 -    /* Extract policy from multiboot.  */
   12.58 -    extract_acm_policy(mbi, &initrdidx, &_policy_start, &_policy_len);
   12.59 -
   12.60 -    /* initialize access control security module */
   12.61 -    acm_init(_policy_start, _policy_len);
   12.62 -
   12.63      /* Create initial domain 0. */
   12.64      dom0 = domain_create(0, 0, DOM0_SSIDREF);
   12.65      if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
    13.1 --- a/xen/arch/x86/x86_32/entry.S	Fri Aug 31 11:37:20 2007 +0100
    13.2 +++ b/xen/arch/x86/x86_32/entry.S	Fri Aug 31 11:41:49 2007 +0100
    13.3 @@ -665,7 +665,7 @@ ENTRY(hypercall_table)
    13.4          .long do_vcpu_op
    13.5          .long do_ni_hypercall       /* 25 */
    13.6          .long do_mmuext_op
    13.7 -        .long do_acm_op
    13.8 +        .long do_xsm_op
    13.9          .long do_nmi_op
   13.10          .long do_sched_op
   13.11          .long do_callback_op        /* 30 */
   13.12 @@ -676,7 +676,6 @@ ENTRY(hypercall_table)
   13.13          .long do_sysctl             /* 35 */
   13.14          .long do_domctl
   13.15          .long do_kexec_op
   13.16 -        .long do_xsm_op
   13.17          .rept NR_hypercalls-((.-hypercall_table)/4)
   13.18          .long do_ni_hypercall
   13.19          .endr
   13.20 @@ -709,7 +708,7 @@ ENTRY(hypercall_args_table)
   13.21          .byte 3 /* do_vcpu_op           */
   13.22          .byte 0 /* do_ni_hypercall      */  /* 25 */
   13.23          .byte 4 /* do_mmuext_op         */
   13.24 -        .byte 1 /* do_acm_op            */
   13.25 +        .byte 1 /* do_xsm_op            */
   13.26          .byte 2 /* do_nmi_op            */
   13.27          .byte 2 /* do_sched_op          */
   13.28          .byte 2 /* do_callback_op       */  /* 30 */
   13.29 @@ -720,7 +719,6 @@ ENTRY(hypercall_args_table)
   13.30          .byte 1 /* do_sysctl            */  /* 35 */
   13.31          .byte 1 /* do_domctl            */
   13.32          .byte 2 /* do_kexec_op          */
   13.33 -        .byte 1 /* do_xsm_op            */
   13.34          .rept NR_hypercalls-(.-hypercall_args_table)
   13.35          .byte 0 /* do_ni_hypercall      */
   13.36          .endr
    14.1 --- a/xen/arch/x86/x86_64/compat/entry.S	Fri Aug 31 11:37:20 2007 +0100
    14.2 +++ b/xen/arch/x86/x86_64/compat/entry.S	Fri Aug 31 11:41:49 2007 +0100
    14.3 @@ -331,7 +331,7 @@ ENTRY(compat_hypercall_table)
    14.4          .quad compat_vcpu_op
    14.5          .quad compat_ni_hypercall       /* 25 */
    14.6          .quad compat_mmuext_op
    14.7 -        .quad do_acm_op
    14.8 +        .quad do_xsm_op
    14.9          .quad compat_nmi_op
   14.10          .quad compat_sched_op
   14.11          .quad compat_callback_op        /* 30 */
   14.12 @@ -374,7 +374,7 @@ ENTRY(compat_hypercall_args_table)
   14.13          .byte 3 /* compat_vcpu_op           */
   14.14          .byte 0 /* compat_ni_hypercall      */  /* 25 */
   14.15          .byte 4 /* compat_mmuext_op         */
   14.16 -        .byte 1 /* do_acm_op                */
   14.17 +        .byte 1 /* do_xsm_op                */
   14.18          .byte 2 /* compat_nmi_op            */
   14.19          .byte 2 /* compat_sched_op          */
   14.20          .byte 2 /* compat_callback_op       */  /* 30 */
    15.1 --- a/xen/arch/x86/x86_64/entry.S	Fri Aug 31 11:37:20 2007 +0100
    15.2 +++ b/xen/arch/x86/x86_64/entry.S	Fri Aug 31 11:41:49 2007 +0100
    15.3 @@ -601,7 +601,7 @@ ENTRY(hypercall_table)
    15.4          .quad do_vcpu_op
    15.5          .quad do_set_segment_base   /* 25 */
    15.6          .quad do_mmuext_op
    15.7 -        .quad do_acm_op
    15.8 +        .quad do_xsm_op
    15.9          .quad do_nmi_op
   15.10          .quad do_sched_op
   15.11          .quad do_callback_op        /* 30 */
   15.12 @@ -612,7 +612,6 @@ ENTRY(hypercall_table)
   15.13          .quad do_sysctl             /* 35 */
   15.14          .quad do_domctl
   15.15          .quad do_kexec_op
   15.16 -        .quad do_xsm_op
   15.17          .rept NR_hypercalls-((.-hypercall_table)/8)
   15.18          .quad do_ni_hypercall
   15.19          .endr
   15.20 @@ -645,7 +644,7 @@ ENTRY(hypercall_args_table)
   15.21          .byte 3 /* do_vcpu_op           */
   15.22          .byte 2 /* do_set_segment_base  */  /* 25 */
   15.23          .byte 4 /* do_mmuext_op         */
   15.24 -        .byte 1 /* do_acm_op            */
   15.25 +        .byte 1 /* do_xsm_op            */
   15.26          .byte 2 /* do_nmi_op            */
   15.27          .byte 2 /* do_sched_op          */
   15.28          .byte 2 /* do_callback_op       */  /* 30 */
    16.1 --- a/xen/common/Makefile	Fri Aug 31 11:37:20 2007 +0100
    16.2 +++ b/xen/common/Makefile	Fri Aug 31 11:41:49 2007 +0100
    16.3 @@ -1,4 +1,3 @@
    16.4 -obj-y += acm_ops.o
    16.5  obj-y += bitmap.o
    16.6  obj-y += domctl.o
    16.7  obj-y += domain.o
    17.1 --- a/xen/common/acm_ops.c	Fri Aug 31 11:37:20 2007 +0100
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,212 +0,0 @@
    17.4 -/******************************************************************************
    17.5 - * acm_ops.c
    17.6 - *
    17.7 - * Copyright (C) 2005 IBM Corporation
    17.8 - *
    17.9 - * Author:
   17.10 - * Reiner Sailer <sailer@watson.ibm.com>
   17.11 - *
   17.12 - * This program is free software; you can redistribute it and/or
   17.13 - * modify it under the terms of the GNU General Public License as
   17.14 - * published by the Free Software Foundation, version 2 of the
   17.15 - * License.
   17.16 - *
   17.17 - * Process acm command requests from guest OS.
   17.18 - */
   17.19 -
   17.20 -#include <xen/config.h>
   17.21 -#include <xen/types.h>
   17.22 -#include <xen/lib.h>
   17.23 -#include <xen/mm.h>
   17.24 -#include <public/acm.h>
   17.25 -#include <public/acm_ops.h>
   17.26 -#include <xen/sched.h>
   17.27 -#include <xen/event.h>
   17.28 -#include <xen/trace.h>
   17.29 -#include <xen/console.h>
   17.30 -#include <xen/guest_access.h>
   17.31 -#include <acm/acm_hooks.h>
   17.32 -
   17.33 -#ifndef ACM_SECURITY
   17.34 -
   17.35 -long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
   17.36 -{
   17.37 -    return -ENOSYS;
   17.38 -}
   17.39 -
   17.40 -#else
   17.41 -
   17.42 -int acm_authorize_acm_ops(struct domain *d)
   17.43 -{
   17.44 -    /* currently, policy management functions are restricted to privileged domains */
   17.45 -    return (IS_PRIV(d) ? 0 : -EPERM);
   17.46 -}
   17.47 -
   17.48 -
   17.49 -long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
   17.50 -{
   17.51 -    long rc = -EFAULT;
   17.52 -    struct xen_acmctl curop, *op = &curop;
   17.53 -
   17.54 -    if (acm_authorize_acm_ops(current->domain))
   17.55 -        return -EPERM;
   17.56 -
   17.57 -    if ( copy_from_guest(op, u_acmctl, 1) )
   17.58 -        return -EFAULT;
   17.59 -
   17.60 -    if (op->interface_version != ACM_INTERFACE_VERSION)
   17.61 -        return -EACCES;
   17.62 -
   17.63 -    switch ( op->cmd )
   17.64 -    {
   17.65 -
   17.66 -    case ACMOP_setpolicy: {
   17.67 -        rc = acm_set_policy(op->u.setpolicy.pushcache,
   17.68 -                            op->u.setpolicy.pushcache_size);
   17.69 -        break;
   17.70 -    }
   17.71 -
   17.72 -    case ACMOP_getpolicy: {
   17.73 -        rc = acm_get_policy(op->u.getpolicy.pullcache,
   17.74 -                            op->u.getpolicy.pullcache_size);
   17.75 -        break;
   17.76 -    }
   17.77 -
   17.78 -    case ACMOP_dumpstats: {
   17.79 -        rc = acm_dump_statistics(op->u.dumpstats.pullcache,
   17.80 -                                 op->u.dumpstats.pullcache_size);
   17.81 -        break;
   17.82 -    }
   17.83 -
   17.84 -    case ACMOP_getssid: {
   17.85 -        ssidref_t ssidref;
   17.86 -
   17.87 -        if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
   17.88 -            ssidref = op->u.getssid.id.ssidref;
   17.89 -        else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
   17.90 -        {
   17.91 -            struct domain *subj = rcu_lock_domain_by_id(op->u.getssid.id.domainid);
   17.92 -            if (!subj)
   17.93 -            {
   17.94 -                rc = -ESRCH; /* domain not found */
   17.95 -                break;
   17.96 -            }
   17.97 -            if (subj->ssid == NULL)
   17.98 -            {
   17.99 -                rcu_unlock_domain(subj);
  17.100 -                rc = -ESRCH;
  17.101 -                break;
  17.102 -            }
  17.103 -            ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
  17.104 -            rcu_unlock_domain(subj);
  17.105 -        }
  17.106 -        else
  17.107 -        {
  17.108 -            rc = -ESRCH;
  17.109 -            break;
  17.110 -        }
  17.111 -        rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
  17.112 -                          op->u.getssid.ssidbuf_size);
  17.113 -        break;
  17.114 -    }
  17.115 -
  17.116 -    case ACMOP_getdecision: {
  17.117 -        ssidref_t ssidref1, ssidref2;
  17.118 -
  17.119 -        if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
  17.120 -            ssidref1 = op->u.getdecision.id1.ssidref;
  17.121 -        else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
  17.122 -        {
  17.123 -            struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
  17.124 -            if (!subj)
  17.125 -            {
  17.126 -                rc = -ESRCH; /* domain not found */
  17.127 -                break;
  17.128 -            }
  17.129 -            if (subj->ssid == NULL)
  17.130 -            {
  17.131 -                rcu_unlock_domain(subj);
  17.132 -                rc = -ESRCH;
  17.133 -                break;
  17.134 -            }
  17.135 -            ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
  17.136 -            rcu_unlock_domain(subj);
  17.137 -        }
  17.138 -        else
  17.139 -        {
  17.140 -            rc = -ESRCH;
  17.141 -            break;
  17.142 -        }
  17.143 -        if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
  17.144 -            ssidref2 = op->u.getdecision.id2.ssidref;
  17.145 -        else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
  17.146 -        {
  17.147 -            struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
  17.148 -            if (!subj)
  17.149 -            {
  17.150 -                rc = -ESRCH; /* domain not found */
  17.151 -                break;;
  17.152 -            }
  17.153 -            if (subj->ssid == NULL)
  17.154 -            {
  17.155 -                rcu_unlock_domain(subj);
  17.156 -                rc = -ESRCH;
  17.157 -                break;
  17.158 -            }
  17.159 -            ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
  17.160 -            rcu_unlock_domain(subj);
  17.161 -        }
  17.162 -        else
  17.163 -        {
  17.164 -            rc = -ESRCH;
  17.165 -            break;
  17.166 -        }
  17.167 -        rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
  17.168 -
  17.169 -        if (rc == ACM_ACCESS_PERMITTED)
  17.170 -        {
  17.171 -            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
  17.172 -            rc = 0;
  17.173 -        }
  17.174 -        else if  (rc == ACM_ACCESS_DENIED)
  17.175 -        {
  17.176 -            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
  17.177 -            rc = 0;
  17.178 -        }
  17.179 -        else
  17.180 -            rc = -ESRCH;
  17.181 -
  17.182 -        if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
  17.183 -            rc = -EFAULT;
  17.184 -        break;
  17.185 -    }
  17.186 -
  17.187 -    case ACMOP_chgpolicy: {
  17.188 -        rc = acm_change_policy(&op->u.change_policy);
  17.189 -        break;
  17.190 -    }
  17.191 -
  17.192 -    case ACMOP_relabeldoms: {
  17.193 -        rc = acm_relabel_domains(&op->u.relabel_doms);
  17.194 -        break;
  17.195 -    }
  17.196 -
  17.197 -    default:
  17.198 -        rc = -ENOSYS;
  17.199 -        break;
  17.200 -    }
  17.201 -
  17.202 -    return rc;
  17.203 -}
  17.204 -
  17.205 -#endif
  17.206 -
  17.207 -/*
  17.208 - * Local variables:
  17.209 - * mode: C
  17.210 - * c-set-style: "BSD"
  17.211 - * c-basic-offset: 4
  17.212 - * tab-width: 4
  17.213 - * indent-tabs-mode: nil
  17.214 - * End:
  17.215 - */
    18.1 --- a/xen/common/domain.c	Fri Aug 31 11:37:20 2007 +0100
    18.2 +++ b/xen/common/domain.c	Fri Aug 31 11:41:49 2007 +0100
    18.3 @@ -28,7 +28,6 @@
    18.4  #include <asm/debugger.h>
    18.5  #include <public/sched.h>
    18.6  #include <public/vcpu.h>
    18.7 -#include <acm/acm_hooks.h>
    18.8  #include <xsm/xsm.h>
    18.9  
   18.10  /* Protect updates/reads (resp.) of domain_list and domain_hash. */
   18.11 @@ -189,7 +188,7 @@ struct domain *domain_create(
   18.12      domid_t domid, unsigned int domcr_flags, ssidref_t ssidref)
   18.13  {
   18.14      struct domain *d, **pd;
   18.15 -    enum { INIT_evtchn = 1, INIT_gnttab = 2, INIT_acm = 4, INIT_arch = 8 }; 
   18.16 +    enum { INIT_evtchn = 1, INIT_gnttab = 2, INIT_arch = 8 }; 
   18.17      int init_status = 0;
   18.18  
   18.19      if ( (d = alloc_domain(domid)) == NULL )
   18.20 @@ -215,10 +214,6 @@ struct domain *domain_create(
   18.21          if ( grant_table_create(d) != 0 )
   18.22              goto fail;
   18.23          init_status |= INIT_gnttab;
   18.24 -
   18.25 -        if ( acm_domain_create(d, ssidref) != 0 )
   18.26 -            goto fail;
   18.27 -        init_status |= INIT_acm;
   18.28      }
   18.29  
   18.30      if ( arch_domain_create(d) != 0 )
   18.31 @@ -254,8 +249,6 @@ struct domain *domain_create(
   18.32      atomic_set(&d->refcnt, DOMAIN_DESTROYED);
   18.33      if ( init_status & INIT_arch )
   18.34          arch_domain_destroy(d);
   18.35 -    if ( init_status & INIT_acm )
   18.36 -        acm_domain_destroy(d);
   18.37      if ( init_status & INIT_gnttab )
   18.38          grant_table_destroy(d);
   18.39      if ( init_status & INIT_evtchn )
   18.40 @@ -483,8 +476,6 @@ static void complete_domain_destroy(stru
   18.41          sched_destroy_vcpu(v);
   18.42      }
   18.43  
   18.44 -    acm_domain_destroy(d);
   18.45 -
   18.46      rangeset_domain_destroy(d);
   18.47  
   18.48      grant_table_destroy(d);
    19.1 --- a/xen/common/domctl.c	Fri Aug 31 11:37:20 2007 +0100
    19.2 +++ b/xen/common/domctl.c	Fri Aug 31 11:41:49 2007 +0100
    19.3 @@ -23,7 +23,6 @@
    19.4  #include <xen/paging.h>
    19.5  #include <asm/current.h>
    19.6  #include <public/domctl.h>
    19.7 -#include <acm/acm_hooks.h>
    19.8  #include <xsm/xsm.h>
    19.9  
   19.10  extern long arch_do_domctl(
   19.11 @@ -124,11 +123,6 @@ void getdomaininfo(struct domain *d, str
   19.12      if ( is_hvm_domain(d) )
   19.13          info->flags |= XEN_DOMINF_hvm_guest;
   19.14  
   19.15 -    if ( d->ssid != NULL )
   19.16 -        info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
   19.17 -    else    
   19.18 -        info->ssidref = ACM_DEFAULT_SSID;
   19.19 -
   19.20      xsm_security_domaininfo(d, info);
   19.21  
   19.22      info->tot_pages         = d->tot_pages;
    20.1 --- a/xen/common/event_channel.c	Fri Aug 31 11:37:20 2007 +0100
    20.2 +++ b/xen/common/event_channel.c	Fri Aug 31 11:41:49 2007 +0100
    20.3 @@ -29,7 +29,6 @@
    20.4  
    20.5  #include <public/xen.h>
    20.6  #include <public/event_channel.h>
    20.7 -#include <acm/acm_hooks.h>
    20.8  #include <xsm/xsm.h>
    20.9  
   20.10  #define bucket_from_port(d,p) \
   20.11 @@ -122,9 +121,6 @@ static long evtchn_alloc_unbound(evtchn_
   20.12      domid_t        dom = alloc->dom;
   20.13      long           rc;
   20.14  
   20.15 -    if ( (rc = acm_pre_eventchannel_unbound(dom, alloc->remote_dom)) != 0 )
   20.16 -        return rc;
   20.17 -
   20.18      if ( dom == DOMID_SELF )
   20.19          dom = current->domain->domain_id;
   20.20      else if ( !IS_PRIV(current->domain) )
   20.21 @@ -166,9 +162,6 @@ static long evtchn_bind_interdomain(evtc
   20.22      domid_t        rdom = bind->remote_dom;
   20.23      long           rc;
   20.24  
   20.25 -    if ( (rc = acm_pre_eventchannel_interdomain(rdom)) != 0 )
   20.26 -        return rc;
   20.27 -
   20.28      if ( rdom == DOMID_SELF )
   20.29          rdom = current->domain->domain_id;
   20.30  
    21.1 --- a/xen/common/grant_table.c	Fri Aug 31 11:37:20 2007 +0100
    21.2 +++ b/xen/common/grant_table.c	Fri Aug 31 11:41:49 2007 +0100
    21.3 @@ -32,7 +32,6 @@
    21.4  #include <xen/trace.h>
    21.5  #include <xen/guest_access.h>
    21.6  #include <xen/domain_page.h>
    21.7 -#include <acm/acm_hooks.h>
    21.8  #include <xsm/xsm.h>
    21.9  
   21.10  #ifndef max_nr_grant_frames
   21.11 @@ -212,12 +211,6 @@ static void
   21.12          return;
   21.13      }
   21.14  
   21.15 -    if ( acm_pre_grant_map_ref(op->dom) )
   21.16 -    {
   21.17 -        op->status = GNTST_permission_denied;
   21.18 -        return;
   21.19 -    }
   21.20 -
   21.21      if ( unlikely((rd = rcu_lock_domain_by_id(op->dom)) == NULL) )
   21.22      {
   21.23          gdprintk(XENLOG_INFO, "Could not find domain %d\n", op->dom);
    22.1 --- a/xen/include/acm/acm_hooks.h	Fri Aug 31 11:37:20 2007 +0100
    22.2 +++ b/xen/include/acm/acm_hooks.h	Fri Aug 31 11:41:49 2007 +0100
    22.3 @@ -145,8 +145,6 @@ static inline int acm_pre_grant_map_ref(
    22.4  { return 0; }
    22.5  static inline int acm_pre_grant_setup(domid_t id) 
    22.6  { return 0; }
    22.7 -static inline int acm_init(char *policy_start, unsigned long policy_len)
    22.8 -{ return 0; }
    22.9  static inline int acm_is_policy(char *buf, unsigned long len)
   22.10  { return 0; }
   22.11  static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
   22.12 @@ -331,8 +329,6 @@ static inline int acm_authorization(ssid
   22.13  }
   22.14  
   22.15  
   22.16 -extern int acm_init(char *policy_start, unsigned long policy_len);
   22.17 -
   22.18  /* Return true iff buffer has an acm policy magic number.  */
   22.19  extern int acm_is_policy(char *buf, unsigned long len);
   22.20  
    23.1 --- a/xen/include/public/acm.h	Fri Aug 31 11:37:20 2007 +0100
    23.2 +++ b/xen/include/public/acm.h	Fri Aug 31 11:41:49 2007 +0100
    23.3 @@ -150,8 +150,8 @@ struct acm_policy_version
    23.4   * tools that assume packed representations (e.g. the java tool)
    23.5   */
    23.6  struct acm_policy_buffer {
    23.7 +    uint32_t magic;
    23.8      uint32_t policy_version; /* ACM_POLICY_VERSION */
    23.9 -    uint32_t magic;
   23.10      uint32_t len;
   23.11      uint32_t policy_reference_offset;
   23.12      uint32_t primary_policy_code;
    24.1 --- a/xen/include/public/xen.h	Fri Aug 31 11:37:20 2007 +0100
    24.2 +++ b/xen/include/public/xen.h	Fri Aug 31 11:41:49 2007 +0100
    24.3 @@ -69,7 +69,7 @@
    24.4  #define __HYPERVISOR_vcpu_op              24
    24.5  #define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
    24.6  #define __HYPERVISOR_mmuext_op            26
    24.7 -#define __HYPERVISOR_acm_op               27
    24.8 +#define __HYPERVISOR_xsm_op               27
    24.9  #define __HYPERVISOR_nmi_op               28
   24.10  #define __HYPERVISOR_sched_op             29
   24.11  #define __HYPERVISOR_callback_op          30
   24.12 @@ -80,7 +80,6 @@
   24.13  #define __HYPERVISOR_sysctl               35
   24.14  #define __HYPERVISOR_domctl               36
   24.15  #define __HYPERVISOR_kexec_op             37
   24.16 -#define __HYPERVISOR_xsm_op               38
   24.17  
   24.18  /* Architecture-specific hypercall definitions. */
   24.19  #define __HYPERVISOR_arch_0               48
    25.1 --- a/xen/include/xen/hypercall.h	Fri Aug 31 11:37:20 2007 +0100
    25.2 +++ b/xen/include/xen/hypercall.h	Fri Aug 31 11:41:49 2007 +0100
    25.3 @@ -12,7 +12,6 @@
    25.4  #include <public/domctl.h>
    25.5  #include <public/sysctl.h>
    25.6  #include <public/platform.h>
    25.7 -#include <public/acm_ops.h>
    25.8  #include <public/event_channel.h>
    25.9  #include <asm/hypercall.h>
   25.10  #include <xsm/xsm.h>
   25.11 @@ -98,10 +97,6 @@ do_vcpu_op(
   25.12      XEN_GUEST_HANDLE(void) arg);
   25.13  
   25.14  extern long
   25.15 -do_acm_op(
   25.16 -    XEN_GUEST_HANDLE(xen_acmctl_t) arg);
   25.17 -
   25.18 -extern long
   25.19  do_nmi_op(
   25.20      unsigned int cmd,
   25.21      XEN_GUEST_HANDLE(void) arg);
   25.22 @@ -117,6 +112,10 @@ do_kexec_op(
   25.23      int arg1,
   25.24      XEN_GUEST_HANDLE(void) arg);
   25.25  
   25.26 +extern long
   25.27 +do_xsm_op(
   25.28 +    XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
   25.29 +
   25.30  #ifdef CONFIG_COMPAT
   25.31  
   25.32  extern int
   25.33 @@ -126,8 +125,4 @@ compat_memory_op(
   25.34  
   25.35  #endif
   25.36  
   25.37 -extern long
   25.38 -do_xsm_op(
   25.39 -    XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
   25.40 -
   25.41  #endif /* __XEN_HYPERCALL_H__ */
    26.1 --- a/xen/xsm/Makefile	Fri Aug 31 11:37:20 2007 +0100
    26.2 +++ b/xen/xsm/Makefile	Fri Aug 31 11:41:49 2007 +0100
    26.3 @@ -5,3 +5,4 @@ obj-y += dummy.o
    26.4  endif
    26.5  
    26.6  subdir-$(FLASK_ENABLE) += flask
    26.7 +subdir-$(ACM_SECURITY) += acm
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/xen/xsm/acm/Makefile	Fri Aug 31 11:41:49 2007 +0100
    27.3 @@ -0,0 +1,7 @@
    27.4 +obj-y += acm_core.o 
    27.5 +obj-y += acm_policy.o
    27.6 +obj-y += acm_simple_type_enforcement_hooks.o
    27.7 +obj-y += acm_chinesewall_hooks.o
    27.8 +obj-y += acm_null_hooks.o
    27.9 +obj-y += acm_xsm_hooks.o
   27.10 +obj-y += acm_ops.o
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/xen/xsm/acm/acm_chinesewall_hooks.c	Fri Aug 31 11:41:49 2007 +0100
    28.3 @@ -0,0 +1,724 @@
    28.4 +/****************************************************************
    28.5 + * acm_chinesewall_hooks.c
    28.6 + * 
    28.7 + * Copyright (C) 2005 IBM Corporation
    28.8 + *
    28.9 + * Author:
   28.10 + * Reiner Sailer <sailer@watson.ibm.com>
   28.11 + *
   28.12 + * Contributions:
   28.13 + * Stefan Berger <stefanb@watson.ibm.com>
   28.14 + *
   28.15 + * This program is free software; you can redistribute it and/or
   28.16 + * modify it under the terms of the GNU General Public License as
   28.17 + * published by the Free Software Foundation, version 2 of the
   28.18 + * License.
   28.19 + *
   28.20 + * sHype Chinese Wall Policy for Xen
   28.21 + *    This code implements the hooks that are called
   28.22 + *    throughout Xen operations and decides authorization
   28.23 + *    based on domain types and Chinese Wall conflict type 
   28.24 + *    sets. The CHWALL policy decides if a new domain can be started
   28.25 + *    based on the types of running domains and the type of the
   28.26 + *    new domain to be started. If the new domain's type is in
   28.27 + *    conflict with types of running domains, then this new domain
   28.28 + *    is not allowed to be created. A domain can have multiple types,
   28.29 + *    in which case all types of a new domain must be conflict-free
   28.30 + *    with all types of already running domains.
   28.31 + *
   28.32 + * indent -i4 -kr -nut
   28.33 + *
   28.34 + */
   28.35 +
   28.36 +#include <xen/config.h>
   28.37 +#include <xen/errno.h>
   28.38 +#include <xen/types.h>
   28.39 +#include <xen/lib.h>
   28.40 +#include <xen/delay.h>
   28.41 +#include <xen/sched.h>
   28.42 +#include <public/acm.h>
   28.43 +#include <asm/atomic.h>
   28.44 +#include <acm/acm_core.h>
   28.45 +#include <acm/acm_hooks.h>
   28.46 +#include <acm/acm_endian.h>
   28.47 +#include <acm/acm_core.h>
   28.48 +
   28.49 +ssidref_t dom0_chwall_ssidref = 0x0001;
   28.50 +
   28.51 +/* local cache structures for chinese wall policy */
   28.52 +struct chwall_binary_policy chwall_bin_pol;
   28.53 +
   28.54 +/*
   28.55 + * Initializing chinese wall policy (will be filled by policy partition
   28.56 + * using setpolicy command)
   28.57 + */
   28.58 +int acm_init_chwall_policy(void)
   28.59 +{
   28.60 +    /* minimal startup policy; policy write-locked already */
   28.61 +    chwall_bin_pol.max_types = 1;
   28.62 +    chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref;
   28.63 +    chwall_bin_pol.max_conflictsets = 1;
   28.64 +    chwall_bin_pol.ssidrefs =
   28.65 +        (domaintype_t *) xmalloc_array(domaintype_t,
   28.66 +                                       chwall_bin_pol.max_ssidrefs *
   28.67 +                                       chwall_bin_pol.max_types);
   28.68 +    chwall_bin_pol.conflict_sets =
   28.69 +        (domaintype_t *) xmalloc_array(domaintype_t,
   28.70 +                                       chwall_bin_pol.max_conflictsets *
   28.71 +                                       chwall_bin_pol.max_types);
   28.72 +    chwall_bin_pol.running_types =
   28.73 +        (domaintype_t *) xmalloc_array(domaintype_t,
   28.74 +                                       chwall_bin_pol.max_types);
   28.75 +    chwall_bin_pol.conflict_aggregate_set =
   28.76 +        (domaintype_t *) xmalloc_array(domaintype_t,
   28.77 +                                       chwall_bin_pol.max_types);
   28.78 +
   28.79 +    if ( (chwall_bin_pol.conflict_sets == NULL)
   28.80 +        || (chwall_bin_pol.running_types == NULL)
   28.81 +        || (chwall_bin_pol.ssidrefs == NULL)
   28.82 +        || (chwall_bin_pol.conflict_aggregate_set == NULL) )
   28.83 +        return ACM_INIT_SSID_ERROR;
   28.84 +
   28.85 +    /* initialize state */
   28.86 +    memset((void *) chwall_bin_pol.ssidrefs, 0,
   28.87 +           chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types *
   28.88 +           sizeof(domaintype_t));
   28.89 +    memset((void *) chwall_bin_pol.conflict_sets, 0,
   28.90 +           chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types *
   28.91 +           sizeof(domaintype_t));
   28.92 +    memset((void *) chwall_bin_pol.running_types, 0,
   28.93 +           chwall_bin_pol.max_types * sizeof(domaintype_t));
   28.94 +    memset((void *) chwall_bin_pol.conflict_aggregate_set, 0,
   28.95 +           chwall_bin_pol.max_types * sizeof(domaintype_t));
   28.96 +    return ACM_OK;
   28.97 +}
   28.98 +
   28.99 +
  28.100 +static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
  28.101 +{
  28.102 +    struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
  28.103 +    traceprintk("%s.\n", __func__);
  28.104 +
  28.105 +    if ( chwall_ssidp == NULL )
  28.106 +        return ACM_INIT_SSID_ERROR;
  28.107 +
  28.108 +    chwall_ssidp->chwall_ssidref =
  28.109 +        GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
  28.110 +
  28.111 +    if ( chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
  28.112 +    {
  28.113 +        printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset "
  28.114 +                "(0).\n",
  28.115 +                __func__, chwall_ssidp->chwall_ssidref);
  28.116 +        xfree(chwall_ssidp);
  28.117 +        return ACM_INIT_SSID_ERROR;
  28.118 +    }
  28.119 +    (*chwall_ssid) = chwall_ssidp;
  28.120 +    printkd("%s: determined chwall_ssidref to %x.\n",
  28.121 +            __func__, chwall_ssidp->chwall_ssidref);
  28.122 +    return ACM_OK;
  28.123 +}
  28.124 +
  28.125 +
  28.126 +static void chwall_free_domain_ssid(void *chwall_ssid)
  28.127 +{
  28.128 +    xfree(chwall_ssid);
  28.129 +    return;
  28.130 +}
  28.131 +
  28.132 +
  28.133 +/* dump chinese wall cache; policy read-locked already */
  28.134 +static int chwall_dump_policy(u8 * buf, u32 buf_size)
  28.135 +{
  28.136 +    struct acm_chwall_policy_buffer *chwall_buf =
  28.137 +        (struct acm_chwall_policy_buffer *) buf;
  28.138 +    int ret = 0;
  28.139 +
  28.140 +    if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
  28.141 +        return -EINVAL;
  28.142 +
  28.143 +    chwall_buf->chwall_max_types = cpu_to_be32(chwall_bin_pol.max_types);
  28.144 +    chwall_buf->chwall_max_ssidrefs = cpu_to_be32(chwall_bin_pol.max_ssidrefs);
  28.145 +    chwall_buf->policy_code = cpu_to_be32(ACM_CHINESE_WALL_POLICY);
  28.146 +    chwall_buf->chwall_ssid_offset =
  28.147 +        cpu_to_be32(sizeof(struct acm_chwall_policy_buffer));
  28.148 +    chwall_buf->chwall_max_conflictsets =
  28.149 +        cpu_to_be32(chwall_bin_pol.max_conflictsets);
  28.150 +    chwall_buf->chwall_conflict_sets_offset =
  28.151 +        cpu_to_be32(be32_to_cpu(chwall_buf->chwall_ssid_offset) +
  28.152 +              sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
  28.153 +              chwall_bin_pol.max_types);
  28.154 +    chwall_buf->chwall_running_types_offset =
  28.155 +        cpu_to_be32(be32_to_cpu(chwall_buf->chwall_conflict_sets_offset) +
  28.156 +              sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
  28.157 +              chwall_bin_pol.max_types);
  28.158 +    chwall_buf->chwall_conflict_aggregate_offset =
  28.159 +        cpu_to_be32(be32_to_cpu(chwall_buf->chwall_running_types_offset) +
  28.160 +              sizeof(domaintype_t) * chwall_bin_pol.max_types);
  28.161 +
  28.162 +    ret = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset) +
  28.163 +        sizeof(domaintype_t) * chwall_bin_pol.max_types;
  28.164 +
  28.165 +    ret = (ret + 7) & ~7;
  28.166 +
  28.167 +    if ( buf_size < ret )
  28.168 +        return -EINVAL;
  28.169 +
  28.170 +    /* now copy buffers over */
  28.171 +    arrcpy16((u16 *) (buf + be32_to_cpu(chwall_buf->chwall_ssid_offset)),
  28.172 +             chwall_bin_pol.ssidrefs,
  28.173 +             chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
  28.174 +
  28.175 +    arrcpy16((u16 *) (buf +
  28.176 +                      be32_to_cpu(chwall_buf->chwall_conflict_sets_offset)),
  28.177 +             chwall_bin_pol.conflict_sets,
  28.178 +             chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
  28.179 +
  28.180 +    arrcpy16((u16 *) (buf +
  28.181 +                      be32_to_cpu(chwall_buf->chwall_running_types_offset)),
  28.182 +             chwall_bin_pol.running_types, chwall_bin_pol.max_types);
  28.183 +
  28.184 +    arrcpy16((u16 *) (buf +
  28.185 +                      be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset)),
  28.186 +             chwall_bin_pol.conflict_aggregate_set,
  28.187 +             chwall_bin_pol.max_types);
  28.188 +    return ret;
  28.189 +}
  28.190 +
  28.191 +/*
  28.192 + * Adapt security state (running_types and conflict_aggregate_set) to all
  28.193 + * running domains; chwall_init_state is called when a policy is changed
  28.194 + * to bring the security information into a consistent state and to detect
  28.195 + * violations (return != 0) from a security point of view, we simulate
  28.196 + * that all running domains are re-started
  28.197 + */
  28.198 +static int
  28.199 +chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
  28.200 +                  domaintype_t * ssidrefs,
  28.201 +                  domaintype_t * conflict_sets,
  28.202 +                  domaintype_t * running_types,
  28.203 +                  domaintype_t * conflict_aggregate_set,
  28.204 +                  struct acm_sized_buffer *errors /* may be NULL */)
  28.205 +{
  28.206 +    int violation = 0, i, j;
  28.207 +    struct chwall_ssid *chwall_ssid;
  28.208 +    ssidref_t chwall_ssidref;
  28.209 +    struct acm_ssid_domain *rawssid;
  28.210 +
  28.211 +    read_lock(&ssid_list_rwlock);
  28.212 +
  28.213 +    /* go through all domains and adjust policy as if this domain was
  28.214 +     * started now
  28.215 +     */
  28.216 +    for_each_acmssid( rawssid )
  28.217 +    {
  28.218 +        chwall_ssid =
  28.219 +            GET_SSIDP(ACM_CHINESE_WALL_POLICY, rawssid);
  28.220 +        chwall_ssidref = chwall_ssid->chwall_ssidref;
  28.221 +        traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
  28.222 +                    __func__, d->domain_id, chwall_ssidref);
  28.223 +        /* a) adjust types ref-count for running domains */
  28.224 +        for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
  28.225 +            running_types[i] +=
  28.226 +                ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
  28.227 +
  28.228 +        /* b) check for conflict */
  28.229 +        for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
  28.230 +            if ( conflict_aggregate_set[i] &&
  28.231 +                 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i] )
  28.232 +            {
  28.233 +                printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
  28.234 +                       __func__, i);
  28.235 +                violation = 1;
  28.236 +
  28.237 +                acm_array_append_tuple(errors, ACM_CHWALL_CONFLICT, i);
  28.238 +
  28.239 +                goto out;
  28.240 +            }
  28.241 +
  28.242 +        /* set violation and break out of the loop */
  28.243 +        /* c) adapt conflict aggregate set for this domain
  28.244 +         *    (notice conflicts)
  28.245 +         */
  28.246 +        for ( i = 0; i < chwall_buf->chwall_max_conflictsets; i++ )
  28.247 +        {
  28.248 +            int common = 0;
  28.249 +            /* check if conflict_set_i and ssidref have common types */
  28.250 +            for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
  28.251 +                if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
  28.252 +                     ssidrefs[chwall_ssidref *
  28.253 +                              chwall_buf->chwall_max_types + j] )
  28.254 +                {
  28.255 +                    common = 1;
  28.256 +                    break;
  28.257 +                }
  28.258 +
  28.259 +            if ( common == 0 )
  28.260 +                continue;       /* try next conflict set */
  28.261 +
  28.262 +            /* now add types of the conflict set to conflict_aggregate_set
  28.263 +             * (except types in chwall_ssidref)
  28.264 +             */
  28.265 +            for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
  28.266 +                if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
  28.267 +                     !ssidrefs[chwall_ssidref *
  28.268 +                               chwall_buf->chwall_max_types + j] )
  28.269 +                    conflict_aggregate_set[j]++;
  28.270 +        }
  28.271 +    }
  28.272 + out:
  28.273 +    read_unlock(&ssid_list_rwlock);
  28.274 +    return violation;
  28.275 +    /* returning "violation != 0" means that the currently running set of
  28.276 +     * domains would not be possible if the new policy had been enforced
  28.277 +     * before starting them; for chinese wall, this means that the new
  28.278 +     * policy includes at least one conflict set of which more than one
  28.279 +     * type is currently running
  28.280 +     */
  28.281 +}
  28.282 +
  28.283 +
  28.284 +int
  28.285 +do_chwall_init_state_curr(struct acm_sized_buffer *errors)
  28.286 +{
  28.287 +    struct acm_chwall_policy_buffer chwall_buf =
  28.288 +    {
  28.289 +         /* only these two are important */
  28.290 +         .chwall_max_types        = chwall_bin_pol.max_types,
  28.291 +         .chwall_max_conflictsets = chwall_bin_pol.max_conflictsets,
  28.292 +    };
  28.293 +    /* reset running_types and aggregate set for recalculation */
  28.294 +    memset(chwall_bin_pol.running_types,
  28.295 +           0x0,
  28.296 +           sizeof(domaintype_t) * chwall_bin_pol.max_types);
  28.297 +    memset(chwall_bin_pol.conflict_aggregate_set,
  28.298 +           0x0,
  28.299 +           sizeof(domaintype_t) * chwall_bin_pol.max_types);
  28.300 +    return chwall_init_state(&chwall_buf,
  28.301 +                             chwall_bin_pol.ssidrefs,
  28.302 +                             chwall_bin_pol.conflict_sets,
  28.303 +                             chwall_bin_pol.running_types,
  28.304 +                             chwall_bin_pol.conflict_aggregate_set,
  28.305 +                             errors);
  28.306 +}
  28.307 +
  28.308 +/*
  28.309 + * Attempt to set the policy. This function must be called in test_only
  28.310 + * mode first to only perform checks. A second call then does the
  28.311 + * actual changes.
  28.312 + */
  28.313 +static int _chwall_update_policy(u8 *buf, u32 buf_size, int test_only,
  28.314 +                                 struct acm_sized_buffer *errors)
  28.315 +{
  28.316 +    int rc = -EFAULT;
  28.317 +    /* policy write-locked already */
  28.318 +    struct acm_chwall_policy_buffer *chwall_buf =
  28.319 +        (struct acm_chwall_policy_buffer *) buf;
  28.320 +    void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL,
  28.321 +         *conflict_aggregate_set = NULL;
  28.322 +
  28.323 +    /* 1. allocate new buffers */
  28.324 +    ssids =
  28.325 +        xmalloc_array(domaintype_t,
  28.326 +                      chwall_buf->chwall_max_types *
  28.327 +                      chwall_buf->chwall_max_ssidrefs);
  28.328 +    conflict_sets =
  28.329 +        xmalloc_array(domaintype_t,
  28.330 +                      chwall_buf->chwall_max_conflictsets *
  28.331 +                      chwall_buf->chwall_max_types);
  28.332 +    running_types =
  28.333 +        xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
  28.334 +    conflict_aggregate_set =
  28.335 +        xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
  28.336 +
  28.337 +    if ( (ssids == NULL) || (conflict_sets == NULL) ||
  28.338 +         (running_types == NULL) || (conflict_aggregate_set == NULL) )
  28.339 +        goto error_free;
  28.340 +
  28.341 +    /* 2. set new policy */
  28.342 +    if ( chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
  28.343 +         chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
  28.344 +         buf_size )
  28.345 +        goto error_free;
  28.346 +
  28.347 +    arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
  28.348 +           sizeof(domaintype_t),
  28.349 +           chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
  28.350 +
  28.351 +    if ( chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
  28.352 +         chwall_buf->chwall_max_types *
  28.353 +         chwall_buf->chwall_max_conflictsets > buf_size )
  28.354 +        goto error_free;
  28.355 +
  28.356 +    arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
  28.357 +           sizeof(domaintype_t),
  28.358 +           chwall_buf->chwall_max_types *
  28.359 +           chwall_buf->chwall_max_conflictsets);
  28.360 +
  28.361 +    /* we also use new state buffers since max_types can change */
  28.362 +    memset(running_types, 0,
  28.363 +           sizeof(domaintype_t) * chwall_buf->chwall_max_types);
  28.364 +    memset(conflict_aggregate_set, 0,
  28.365 +           sizeof(domaintype_t) * chwall_buf->chwall_max_types);
  28.366 +
  28.367 +    /* 3. now re-calculate the state for the new policy based on
  28.368 +     *    running domains; this can fail if new policy is conflicting
  28.369 +     *    with running domains
  28.370 +     */
  28.371 +    if ( chwall_init_state(chwall_buf, ssids,
  28.372 +                           conflict_sets, running_types,
  28.373 +                           conflict_aggregate_set,
  28.374 +                           errors))
  28.375 +    {
  28.376 +        printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
  28.377 +               __func__);
  28.378 +        goto error_free;        /* new policy conflicts with running domains */
  28.379 +    }
  28.380 +
  28.381 +    /* if this was only a test run, exit with ACM_OK */
  28.382 +    if ( test_only )
  28.383 +    {
  28.384 +        rc = ACM_OK;
  28.385 +        goto error_free;
  28.386 +    }
  28.387 +
  28.388 +    /* 4. free old policy buffers, replace with new ones */
  28.389 +    chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
  28.390 +    chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
  28.391 +    chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
  28.392 +    xfree(chwall_bin_pol.ssidrefs);
  28.393 +    xfree(chwall_bin_pol.conflict_aggregate_set);
  28.394 +    xfree(chwall_bin_pol.running_types);
  28.395 +    xfree(chwall_bin_pol.conflict_sets);
  28.396 +    chwall_bin_pol.ssidrefs = ssids;
  28.397 +    chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
  28.398 +    chwall_bin_pol.running_types = running_types;
  28.399 +    chwall_bin_pol.conflict_sets = conflict_sets;
  28.400 +
  28.401 +    return ACM_OK;
  28.402 +
  28.403 + error_free:
  28.404 +    if ( !test_only )
  28.405 +        printk("%s: ERROR setting policy.\n", __func__);
  28.406 +
  28.407 +    xfree(ssids);
  28.408 +    xfree(conflict_sets);
  28.409 +    xfree(running_types);
  28.410 +    xfree(conflict_aggregate_set);
  28.411 +    return rc;
  28.412 +}
  28.413 +
  28.414 +/*
  28.415 + * This function MUST be called before the chwall_ste_policy function!
  28.416 + */
  28.417 +static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
  28.418 +                              struct acm_sized_buffer *errors)
  28.419 +{
  28.420 +    struct acm_chwall_policy_buffer *chwall_buf =
  28.421 +        (struct acm_chwall_policy_buffer *) buf;
  28.422 +
  28.423 +    if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
  28.424 +        return -EINVAL;
  28.425 +
  28.426 +    /* rewrite the policy due to endianess */
  28.427 +    chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code);
  28.428 +    chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version);
  28.429 +    chwall_buf->chwall_max_types =
  28.430 +        be32_to_cpu(chwall_buf->chwall_max_types);
  28.431 +    chwall_buf->chwall_max_ssidrefs =
  28.432 +        be32_to_cpu(chwall_buf->chwall_max_ssidrefs);
  28.433 +    chwall_buf->chwall_max_conflictsets =
  28.434 +        be32_to_cpu(chwall_buf->chwall_max_conflictsets);
  28.435 +    chwall_buf->chwall_ssid_offset =
  28.436 +        be32_to_cpu(chwall_buf->chwall_ssid_offset);
  28.437 +    chwall_buf->chwall_conflict_sets_offset =
  28.438 +        be32_to_cpu(chwall_buf->chwall_conflict_sets_offset);
  28.439 +    chwall_buf->chwall_running_types_offset =
  28.440 +        be32_to_cpu(chwall_buf->chwall_running_types_offset);
  28.441 +    chwall_buf->chwall_conflict_aggregate_offset =
  28.442 +        be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset);
  28.443 +
  28.444 +    /* policy type and version checks */
  28.445 +    if ( (chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
  28.446 +         (chwall_buf->policy_version != ACM_CHWALL_VERSION) )
  28.447 +        return -EINVAL;
  28.448 +
  28.449 +    /* during boot dom0_chwall_ssidref is set */
  28.450 +    if ( is_bootpolicy &&
  28.451 +         (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs) )
  28.452 +        return -EINVAL;
  28.453 +
  28.454 +    return _chwall_update_policy(buf, buf_size, 1, errors);
  28.455 +}
  28.456 +
  28.457 +static int chwall_set_policy(u8 *buf, u32 buf_size)
  28.458 +{
  28.459 +    return _chwall_update_policy(buf, buf_size, 0, NULL);
  28.460 +}
  28.461 +
  28.462 +static int chwall_dump_stats(u8 * buf, u16 len)
  28.463 +{
  28.464 +    /* no stats for Chinese Wall Policy */
  28.465 +    return 0;
  28.466 +}
  28.467 +
  28.468 +static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
  28.469 +{
  28.470 +    int i;
  28.471 +
  28.472 +    /* fill in buffer */
  28.473 +    if ( chwall_bin_pol.max_types > len )
  28.474 +        return -EFAULT;
  28.475 +
  28.476 +    if ( ssidref >= chwall_bin_pol.max_ssidrefs )
  28.477 +        return -EFAULT;
  28.478 +
  28.479 +    /* read types for chwall ssidref */
  28.480 +    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
  28.481 +    {
  28.482 +        if ( chwall_bin_pol.
  28.483 +             ssidrefs[ssidref * chwall_bin_pol.max_types + i] )
  28.484 +            buf[i] = 1;
  28.485 +        else
  28.486 +            buf[i] = 0;
  28.487 +    }
  28.488 +    return chwall_bin_pol.max_types;
  28.489 +}
  28.490 +
  28.491 +/***************************
  28.492 + * Authorization functions
  28.493 + ***************************/
  28.494 +
  28.495 +/* -------- DOMAIN OPERATION HOOKS -----------*/
  28.496 +
  28.497 +static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
  28.498 +{
  28.499 +    ssidref_t chwall_ssidref;
  28.500 +    int i, j;
  28.501 +
  28.502 +    chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
  28.503 +
  28.504 +    if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
  28.505 +    {
  28.506 +        printk("%s: ERROR chwall_ssidref > max(%x).\n",
  28.507 +               __func__, chwall_bin_pol.max_ssidrefs - 1);
  28.508 +        return ACM_ACCESS_DENIED;
  28.509 +    }
  28.510 +
  28.511 +    /* A: chinese wall check for conflicts */
  28.512 +    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
  28.513 +        if ( chwall_bin_pol.conflict_aggregate_set[i] &&
  28.514 +             chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.515 +                                     chwall_bin_pol.max_types + i] )
  28.516 +        {
  28.517 +            printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
  28.518 +            return ACM_ACCESS_DENIED;
  28.519 +        }
  28.520 +
  28.521 +    /* B: chinese wall conflict set adjustment (so that other
  28.522 +     *    other domains simultaneously created are evaluated against
  28.523 +     *    this new set)
  28.524 +     */
  28.525 +    for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
  28.526 +    {
  28.527 +        int common = 0;
  28.528 +        /* check if conflict_set_i and ssidref have common types */
  28.529 +        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
  28.530 +            if ( chwall_bin_pol.
  28.531 +                 conflict_sets[i * chwall_bin_pol.max_types + j]
  28.532 +                 && chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.533 +                                            chwall_bin_pol.max_types + j] )
  28.534 +            {
  28.535 +                common = 1;
  28.536 +                break;
  28.537 +            }
  28.538 +        if ( common == 0 )
  28.539 +            continue;           /* try next conflict set */
  28.540 +        /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
  28.541 +        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
  28.542 +            if ( chwall_bin_pol.
  28.543 +                 conflict_sets[i * chwall_bin_pol.max_types + j]
  28.544 +                 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.545 +                                             chwall_bin_pol.max_types + j])
  28.546 +                 chwall_bin_pol.conflict_aggregate_set[j]++;
  28.547 +    }
  28.548 +    return ACM_ACCESS_PERMITTED;
  28.549 +}
  28.550 +
  28.551 +
  28.552 +static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
  28.553 +{
  28.554 +    int i, j;
  28.555 +    ssidref_t chwall_ssidref;
  28.556 +
  28.557 +    chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
  28.558 +    /* adjust types ref-count for running domains */
  28.559 +    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
  28.560 +        chwall_bin_pol.running_types[i] +=
  28.561 +            chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.562 +                                   chwall_bin_pol.max_types + i];
  28.563 +    if ( domid )
  28.564 +        return;
  28.565 +
  28.566 +    /* Xen does not call pre-create hook for DOM0;
  28.567 +     * to consider type conflicts of any domain with DOM0, we need
  28.568 +     * to adjust the conflict_aggregate for DOM0 here the same way it
  28.569 +     * is done for non-DOM0 domains in the pre-hook */
  28.570 +    printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
  28.571 +            __func__, ssidref, chwall_ssidref);
  28.572 +
  28.573 +    /* chinese wall conflict set adjustment (so that other
  28.574 +     *      other domains simultaneously created are evaluated against this new set)*/
  28.575 +    for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
  28.576 +    {
  28.577 +        int common = 0;
  28.578 +        /* check if conflict_set_i and ssidref have common types */
  28.579 +        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
  28.580 +            if ( chwall_bin_pol.
  28.581 +                 conflict_sets[i * chwall_bin_pol.max_types + j]
  28.582 +                 && chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.583 +                                            chwall_bin_pol.max_types + j] )
  28.584 +            {
  28.585 +                common = 1;
  28.586 +                break;
  28.587 +            }
  28.588 +
  28.589 +        if ( common == 0 )
  28.590 +        {
  28.591 +            /* try next conflict set */
  28.592 +            continue;
  28.593 +        }
  28.594 +
  28.595 +        /* now add types of the conflict set to conflict_aggregate_set
  28.596 +           (except types in chwall_ssidref) */
  28.597 +        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
  28.598 +            if ( chwall_bin_pol.
  28.599 +                 conflict_sets[i * chwall_bin_pol.max_types + j]
  28.600 +                 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.601 +                                             chwall_bin_pol.max_types + j] )
  28.602 +                chwall_bin_pol.conflict_aggregate_set[j]++;
  28.603 +    }
  28.604 +    return;
  28.605 +}
  28.606 +
  28.607 +
  28.608 +/*
  28.609 + * To be called when creating a domain. If this call is unsuccessful,
  28.610 + * no state changes have occurred (adjustments of counters etc.). If it
  28.611 + * was successful, state was changed and can be undone using
  28.612 + * chwall_domain_destroy.
  28.613 + */
  28.614 +static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref,
  28.615 +                                domid_t domid)
  28.616 +{
  28.617 +    int rc;
  28.618 +    read_lock(&acm_bin_pol_rwlock);
  28.619 +
  28.620 +    rc = _chwall_pre_domain_create(subject_ssid, ssidref);
  28.621 +    if ( rc == ACM_ACCESS_PERMITTED )
  28.622 +        _chwall_post_domain_create(domid, ssidref);
  28.623 +
  28.624 +    read_unlock(&acm_bin_pol_rwlock);
  28.625 +    return rc;
  28.626 +}
  28.627 +
  28.628 +/*
  28.629 + * This function undoes everything a successful call to
  28.630 + * chwall_domain_create has done.
  28.631 + */
  28.632 +static void chwall_domain_destroy(void *object_ssid, struct domain *d)
  28.633 +{
  28.634 +    int i, j;
  28.635 +    struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
  28.636 +                                                 (struct acm_ssid_domain *)
  28.637 +                                                 object_ssid);
  28.638 +    ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
  28.639 +
  28.640 +    read_lock(&acm_bin_pol_rwlock);
  28.641 +
  28.642 +    /* adjust running types set */
  28.643 +    for ( i = 0; i < chwall_bin_pol.max_types; i++ )
  28.644 +        chwall_bin_pol.running_types[i] -=
  28.645 +            chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.646 +                                   chwall_bin_pol.max_types + i];
  28.647 +
  28.648 +    /* roll-back: re-adjust conflicting types aggregate */
  28.649 +    for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
  28.650 +    {
  28.651 +        int common = 0;
  28.652 +        /* check if conflict_set_i and ssidref have common types */
  28.653 +        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
  28.654 +            if ( chwall_bin_pol.conflict_sets[i * chwall_bin_pol.max_types + j]
  28.655 +                 && chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.656 +                                            chwall_bin_pol.max_types + j])
  28.657 +            {
  28.658 +                common = 1;
  28.659 +                break;
  28.660 +            }
  28.661 +        if ( common == 0 )
  28.662 +        {
  28.663 +            /* try next conflict set, this one does not include
  28.664 +               any type of chwall_ssidref */
  28.665 +            continue;
  28.666 +        }
  28.667 +
  28.668 +        /* now add types of the conflict set to conflict_aggregate_set
  28.669 +           (except types in chwall_ssidref) */
  28.670 +        for ( j = 0; j < chwall_bin_pol.max_types; j++ )
  28.671 +            if ( chwall_bin_pol.
  28.672 +                 conflict_sets[i * chwall_bin_pol.max_types + j]
  28.673 +                 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
  28.674 +                                             chwall_bin_pol.max_types + j])
  28.675 +                chwall_bin_pol.conflict_aggregate_set[j]--;
  28.676 +    }
  28.677 +
  28.678 +    read_unlock(&acm_bin_pol_rwlock);
  28.679 +
  28.680 +    return;
  28.681 +}
  28.682 +
  28.683 +
  28.684 +static int chwall_is_default_policy(void)
  28.685 +{
  28.686 +    return ( (chwall_bin_pol.max_types    == 1 ) &&
  28.687 +             (chwall_bin_pol.max_ssidrefs == 2 ) );
  28.688 +}
  28.689 +
  28.690 +struct acm_operations acm_chinesewall_ops = {
  28.691 +    /* policy management services */
  28.692 +    .init_domain_ssid = chwall_init_domain_ssid,
  28.693 +    .free_domain_ssid = chwall_free_domain_ssid,
  28.694 +    .dump_binary_policy = chwall_dump_policy,
  28.695 +    .test_binary_policy = chwall_test_policy,
  28.696 +    .set_binary_policy = chwall_set_policy,
  28.697 +    .dump_statistics = chwall_dump_stats,
  28.698 +    .dump_ssid_types = chwall_dump_ssid_types,
  28.699 +    /* domain management control hooks */
  28.700 +    .domain_create = chwall_domain_create,
  28.701 +    .domain_destroy = chwall_domain_destroy,
  28.702 +    /* event channel control hooks */
  28.703 +    .pre_eventchannel_unbound = NULL,
  28.704 +    .fail_eventchannel_unbound = NULL,
  28.705 +    .pre_eventchannel_interdomain = NULL,
  28.706 +    .fail_eventchannel_interdomain = NULL,
  28.707 +    /* grant table control hooks */
  28.708 +    .pre_grant_map_ref = NULL,
  28.709 +    .fail_grant_map_ref = NULL,
  28.710 +    .pre_grant_setup = NULL,
  28.711 +    .fail_grant_setup = NULL,
  28.712 +    /* generic domain-requested decision hooks */
  28.713 +    .sharing = NULL,
  28.714 +    .authorization = NULL,
  28.715 +
  28.716 +    .is_default_policy = chwall_is_default_policy,
  28.717 +};
  28.718 +
  28.719 +/*
  28.720 + * Local variables:
  28.721 + * mode: C
  28.722 + * c-set-style: "BSD"
  28.723 + * c-basic-offset: 4
  28.724 + * tab-width: 4
  28.725 + * indent-tabs-mode: nil
  28.726 + * End:
  28.727 + */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/xen/xsm/acm/acm_core.c	Fri Aug 31 11:41:49 2007 +0100
    29.3 @@ -0,0 +1,402 @@
    29.4 +/****************************************************************
    29.5 + * acm_core.c
    29.6 + * 
    29.7 + * Copyright (C) 2005 IBM Corporation
    29.8 + *
    29.9 + * Author:
   29.10 + * Reiner Sailer <sailer@watson.ibm.com>
   29.11 + *
   29.12 + * Contributors:
   29.13 + * Stefan Berger <stefanb@watson.ibm.com>
   29.14 + *
   29.15 + * This program is free software; you can redistribute it and/or
   29.16 + * modify it under the terms of the GNU General Public License as
   29.17 + * published by the Free Software Foundation, version 2 of the
   29.18 + * License.
   29.19 + *
   29.20 + * sHype access control module (ACM)
   29.21 + *       This file handles initialization of the ACM
   29.22 + *       as well as initializing/freeing security 
   29.23 + *       identifiers for domains (it calls on active
   29.24 + *       policy hook functions).
   29.25 + *
   29.26 + */
   29.27 +
   29.28 +#include <xen/config.h>
   29.29 +#include <xen/errno.h>
   29.30 +#include <xen/types.h>
   29.31 +#include <xen/lib.h>
   29.32 +#include <xen/delay.h>
   29.33 +#include <xen/sched.h>
   29.34 +#include <xen/multiboot.h>
   29.35 +#include <acm/acm_hooks.h>
   29.36 +#include <acm/acm_endian.h>
   29.37 +#include <xsm/xsm.h>
   29.38 +
   29.39 +/* debug: 
   29.40 + *   include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
   29.41 + *   define/undefine this constant to receive / suppress any
   29.42 + *   security hook debug output of sHype
   29.43 + *
   29.44 + *   include/public/acm.h defines a constant ACM_DEBUG
   29.45 + *   define/undefine this constant to receive non-hook-related
   29.46 + *   debug output.
   29.47 + */
   29.48 +
   29.49 +/* function prototypes */
   29.50 +void acm_init_chwall_policy(void);
   29.51 +void acm_init_ste_policy(void);
   29.52 +
   29.53 +extern struct acm_operations acm_chinesewall_ops, 
   29.54 +    acm_simple_type_enforcement_ops, acm_null_ops;
   29.55 +
   29.56 +extern struct xsm_operations acm_xsm_ops;
   29.57 +
   29.58 +/* global ACM policy  (now dynamically determined at boot time) */
   29.59 +u16 acm_active_security_policy = ACM_POLICY_UNDEFINED;
   29.60 +
   29.61 +/* global ops structs called by the hooks */
   29.62 +struct acm_operations *acm_primary_ops = NULL;
   29.63 +/* called in hook if-and-only-if primary succeeds */
   29.64 +struct acm_operations *acm_secondary_ops = NULL;
   29.65 +
   29.66 +/* acm global binary policy (points to 'local' primary and secondary policies */
   29.67 +struct acm_binary_policy acm_bin_pol;
   29.68 +/* acm binary policy lock */
   29.69 +DEFINE_RWLOCK(acm_bin_pol_rwlock);
   29.70 +
   29.71 +/* ACM's only accepted policy name during boot */
   29.72 +char polname[80];
   29.73 +char *acm_accepted_boot_policy_name = NULL;
   29.74 +
   29.75 +/* a lits of all chained ssid structures */
   29.76 +LIST_HEAD(ssid_list);
   29.77 +DEFINE_RWLOCK(ssid_list_rwlock);
   29.78 +
   29.79 +static void __init set_dom0_ssidref(const char *val)
   29.80 +{
   29.81 +    /* expected format:
   29.82 +         ssidref=<hex number>:<policy name>
   29.83 +         Policy name must not have a 'space'.
   29.84 +     */
   29.85 +    const char *c;
   29.86 +    int lo, hi;
   29.87 +    int i;
   29.88 +    int dom0_ssidref = simple_strtoull(val, &c, 0);
   29.89 +
   29.90 +    if (!strncmp(&c[0],":ACM:", 5)) {
   29.91 +        lo = dom0_ssidref & 0xffff;
   29.92 +        if (lo < ACM_MAX_NUM_TYPES && lo >= 1)
   29.93 +            dom0_chwall_ssidref = lo;
   29.94 +        hi = dom0_ssidref >> 16;
   29.95 +        if (hi < ACM_MAX_NUM_TYPES && hi >= 1)
   29.96 +            dom0_ste_ssidref = hi;
   29.97 +        for (i = 0; i < sizeof(polname); i++) {
   29.98 +            polname[i] = c[5+i];
   29.99 +            if (polname[i] == '\0' || polname[i] == '\t' ||
  29.100 +                polname[i] == '\n' || polname[i] == ' '  ||
  29.101 +                polname[i] == ':') {
  29.102 +                break;
  29.103 +            }
  29.104 +        }
  29.105 +        polname[i] = 0;
  29.106 +        acm_accepted_boot_policy_name = polname;
  29.107 +    }
  29.108 +}
  29.109 +
  29.110 +custom_param("ssidref", set_dom0_ssidref);
  29.111 +
  29.112 +int
  29.113 +acm_set_policy_reference(u8 *buf, u32 buf_size)
  29.114 +{
  29.115 +    char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer));
  29.116 +    struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
  29.117 +
  29.118 +    if (acm_accepted_boot_policy_name != NULL) {
  29.119 +        if (strcmp(acm_accepted_boot_policy_name, name)) {
  29.120 +            printk("Policy's name '%s' is not the expected one '%s'.\n",
  29.121 +                   name, acm_accepted_boot_policy_name);
  29.122 +            return ACM_ERROR;
  29.123 +        }
  29.124 +    }
  29.125 +
  29.126 +    acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len));
  29.127 +
  29.128 +    if (!acm_bin_pol.policy_reference_name)
  29.129 +        return -ENOMEM;
  29.130 +    strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len));
  29.131 +
  29.132 +    printk("%s: Activating policy %s\n", __func__,
  29.133 +           acm_bin_pol.policy_reference_name);
  29.134 +    return 0;
  29.135 +}
  29.136 +
  29.137 +int
  29.138 +acm_dump_policy_reference(u8 *buf, u32 buf_size)
  29.139 +{
  29.140 +    struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
  29.141 +    int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
  29.142 +
  29.143 +    ret = (ret + 7) & ~7;
  29.144 +    if (buf_size < ret)
  29.145 +        return -EINVAL;
  29.146 +
  29.147 +    memset(buf, 0, ret);
  29.148 +    pr_buf->len = cpu_to_be32(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
  29.149 +    strlcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
  29.150 +            acm_bin_pol.policy_reference_name,
  29.151 +            be32_to_cpu(pr_buf->len));
  29.152 +    return ret;
  29.153 +}
  29.154 +
  29.155 +int
  29.156 +acm_init_binary_policy(u32 policy_code)
  29.157 +{
  29.158 +    int ret = ACM_OK;
  29.159 +
  29.160 +    acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
  29.161 +    acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
  29.162 +
  29.163 +    write_lock(&acm_bin_pol_rwlock);
  29.164 +
  29.165 +    /* set primary policy component */
  29.166 +    switch ((policy_code) & 0x0f)
  29.167 +    {
  29.168 +
  29.169 +    case ACM_CHINESE_WALL_POLICY:
  29.170 +        acm_init_chwall_policy();
  29.171 +        acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
  29.172 +        acm_primary_ops = &acm_chinesewall_ops;
  29.173 +        break;
  29.174 +
  29.175 +    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
  29.176 +        acm_init_ste_policy();
  29.177 +        acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
  29.178 +        acm_primary_ops = &acm_simple_type_enforcement_ops;
  29.179 +        break;
  29.180 +
  29.181 +    case ACM_NULL_POLICY:
  29.182 +        acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
  29.183 +        acm_primary_ops = &acm_null_ops;
  29.184 +        break;
  29.185 +
  29.186 +    default:
  29.187 +        /* Unknown policy not allowed primary */
  29.188 +        ret = -EINVAL;
  29.189 +        goto out;
  29.190 +    }
  29.191 +
  29.192 +    /* secondary policy component part */
  29.193 +    switch ((policy_code) >> 4)
  29.194 +    {
  29.195 +
  29.196 +    case ACM_NULL_POLICY:
  29.197 +        acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
  29.198 +        acm_secondary_ops = &acm_null_ops;
  29.199 +        break;
  29.200 +
  29.201 +    case ACM_CHINESE_WALL_POLICY:
  29.202 +        if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
  29.203 +        {   /* not a valid combination */
  29.204 +            ret = -EINVAL;
  29.205 +            goto out;
  29.206 +        }
  29.207 +        acm_init_chwall_policy();
  29.208 +        acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
  29.209 +        acm_secondary_ops = &acm_chinesewall_ops;
  29.210 +        break;
  29.211 +
  29.212 +    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
  29.213 +        if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
  29.214 +        {   /* not a valid combination */
  29.215 +            ret = -EINVAL;
  29.216 +            goto out;
  29.217 +        }
  29.218 +        acm_init_ste_policy();
  29.219 +        acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
  29.220 +        acm_secondary_ops = &acm_simple_type_enforcement_ops;
  29.221 +        break;
  29.222 +
  29.223 +    default:
  29.224 +        ret = -EINVAL;
  29.225 +        goto out;
  29.226 +    }
  29.227 +
  29.228 + out:
  29.229 +    write_unlock(&acm_bin_pol_rwlock);
  29.230 +    return ret;
  29.231 +}
  29.232 +
  29.233 +int
  29.234 +acm_is_policy(char *buf, unsigned long len)
  29.235 +{
  29.236 +    struct acm_policy_buffer *pol;
  29.237 +
  29.238 +    if (buf == NULL || len < sizeof(struct acm_policy_buffer))
  29.239 +        return 0;
  29.240 +
  29.241 +    pol = (struct acm_policy_buffer *)buf;
  29.242 +    return be32_to_cpu(pol->magic) == ACM_MAGIC;
  29.243 +}
  29.244 +
  29.245 +
  29.246 +static int
  29.247 +acm_setup(char *policy_start,
  29.248 +          unsigned long policy_len,
  29.249 +          int is_bootpolicy)
  29.250 +{
  29.251 +    int rc = ACM_OK;
  29.252 +    struct acm_policy_buffer *pol;
  29.253 +
  29.254 +    if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
  29.255 +        return rc;
  29.256 +
  29.257 +    pol = (struct acm_policy_buffer *)policy_start;
  29.258 +    if (be32_to_cpu(pol->magic) != ACM_MAGIC)
  29.259 +        return rc;
  29.260 +
  29.261 +    rc = do_acm_set_policy((void *)policy_start, (u32)policy_len,
  29.262 +                           is_bootpolicy,
  29.263 +                           NULL, NULL, NULL);
  29.264 +    if (rc == ACM_OK)
  29.265 +    {
  29.266 +        printkd("Policy len  0x%lx, start at %p.\n",policy_len,policy_start);
  29.267 +    }
  29.268 +    else
  29.269 +    {
  29.270 +        printk("Invalid policy.\n");
  29.271 +        /* load default policy later */
  29.272 +        acm_active_security_policy = ACM_POLICY_UNDEFINED;
  29.273 +    }
  29.274 +    return rc;
  29.275 +}
  29.276 +
  29.277 +
  29.278 +int
  29.279 +acm_init(void)
  29.280 +{
  29.281 +    int ret = ACM_OK;
  29.282 +
  29.283 +    printk("ACM-XSM:  Initializing.\n");
  29.284 +
  29.285 +    /* first try to load the boot policy (uses its own locks) */
  29.286 +    acm_setup(policy_buffer, policy_size, 1);
  29.287 +
  29.288 +    /* a user-provided policy may have any name; only matched during boot */
  29.289 +    acm_accepted_boot_policy_name = NULL;
  29.290 +
  29.291 +    if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
  29.292 +    {
  29.293 +        printk("%s: Enforcing %s boot policy.\n", __func__,
  29.294 +               ACM_POLICY_NAME(acm_active_security_policy));
  29.295 +        goto out;
  29.296 +    }
  29.297 +    /* else continue with the minimal hardcoded default startup policy */
  29.298 +    printk("%s: Loading default policy (%s).\n",
  29.299 +           __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
  29.300 +
  29.301 +    /* (re-)set dom-0 ssidref to default */
  29.302 +    dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001;
  29.303 +
  29.304 +    if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
  29.305 +        ret = -EINVAL;
  29.306 +        goto out;
  29.307 +    }
  29.308 +    acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
  29.309 +    if (acm_active_security_policy != ACM_NULL_POLICY)
  29.310 +        acm_bin_pol.policy_reference_name = "DEFAULT";
  29.311 +    else
  29.312 +        acm_bin_pol.policy_reference_name = "NULL";
  29.313 +
  29.314 + out:
  29.315 +    if (ret != ACM_OK)
  29.316 +    {
  29.317 +        printk("%s: Error initializing policies.\n", __func__);
  29.318 +        /* here one could imagine a clean panic */
  29.319 +        return -EINVAL;
  29.320 +    }
  29.321 +
  29.322 +    if (register_xsm(&acm_xsm_ops))
  29.323 +        panic("ACM-XSM: Unable to register with XSM.\n");
  29.324 +
  29.325 +    return ret;
  29.326 +}
  29.327 +
  29.328 +xsm_initcall(acm_init);
  29.329 +
  29.330 +int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref)
  29.331 +{
  29.332 +    struct acm_ssid_domain *ssid;
  29.333 +    int ret1, ret2;
  29.334 +    if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
  29.335 +    {
  29.336 +        return ACM_INIT_SSID_ERROR;
  29.337 +    }
  29.338 +
  29.339 +    INIT_LIST_HEAD(&ssid->node);
  29.340 +    ssid->datatype       = ACM_DATATYPE_domain;
  29.341 +    ssid->subject        = subj;
  29.342 +    ssid->domainid       = subj->domain_id;
  29.343 +    ssid->primary_ssid   = NULL;
  29.344 +    ssid->secondary_ssid = NULL;
  29.345 +
  29.346 +    if (acm_active_security_policy != ACM_NULL_POLICY)
  29.347 +        ssid->ssidref = ssidref;
  29.348 +    else
  29.349 +        ssid->ssidref = ACM_DEFAULT_SSID;
  29.350 +
  29.351 +    subj->ssid           = ssid;
  29.352 +    /* now fill in primary and secondary parts; we only get here through hooks */
  29.353 +    if (acm_primary_ops->init_domain_ssid != NULL)
  29.354 +        ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
  29.355 +    else
  29.356 +        ret1 = ACM_OK;
  29.357 +
  29.358 +    if (acm_secondary_ops->init_domain_ssid != NULL)
  29.359 +        ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
  29.360 +    else
  29.361 +        ret2 = ACM_OK;
  29.362 +
  29.363 +    if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
  29.364 +    {
  29.365 +        printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
  29.366 +               __func__, subj->domain_id);
  29.367 +        acm_free_domain_ssid(ssid);
  29.368 +        return ACM_INIT_SSID_ERROR;
  29.369 +    }
  29.370 +
  29.371 +    printkd("%s: assigned domain %x the ssidref=%x.\n",
  29.372 +           __func__, subj->domain_id, ssid->ssidref);
  29.373 +    return ACM_OK;
  29.374 +}
  29.375 +
  29.376 +
  29.377 +void
  29.378 +acm_free_domain_ssid(struct acm_ssid_domain *ssid)
  29.379 +{
  29.380 +    /* domain is already gone, just ssid is left */
  29.381 +    if (ssid == NULL)
  29.382 +        return;
  29.383 +
  29.384 +    ssid->subject = NULL;
  29.385 +    if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
  29.386 +        acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
  29.387 +    ssid->primary_ssid = NULL;
  29.388 +    if (acm_secondary_ops->free_domain_ssid != NULL)
  29.389 +        acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
  29.390 +    ssid->secondary_ssid = NULL;
  29.391 +
  29.392 +    xfree(ssid);
  29.393 +    printkd("%s: Freed individual domain ssid (domain=%02x).\n",
  29.394 +            __func__, id);
  29.395 +}
  29.396 +
  29.397 +/*
  29.398 + * Local variables:
  29.399 + * mode: C
  29.400 + * c-set-style: "BSD"
  29.401 + * c-basic-offset: 4
  29.402 + * tab-width: 4
  29.403 + * indent-tabs-mode: nil
  29.404 + * End:
  29.405 + */
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/xen/xsm/acm/acm_null_hooks.c	Fri Aug 31 11:41:49 2007 +0100
    30.3 @@ -0,0 +1,95 @@
    30.4 +/****************************************************************
    30.5 + * acm_null_hooks.c
    30.6 + * 
    30.7 + * Copyright (C) 2005 IBM Corporation
    30.8 + *
    30.9 + * Author:
   30.10 + * Reiner Sailer <sailer@watson.ibm.com>
   30.11 + *
   30.12 + * This program is free software; you can redistribute it and/or
   30.13 + * modify it under the terms of the GNU General Public License as
   30.14 + * published by the Free Software Foundation, version 2 of the
   30.15 + * License.
   30.16 + */
   30.17 +
   30.18 +#include <acm/acm_hooks.h>
   30.19 +
   30.20 +static int
   30.21 +null_init_domain_ssid(void **ssid, ssidref_t ssidref)
   30.22 +{
   30.23 +    return ACM_OK;
   30.24 +}
   30.25 +
   30.26 +static void
   30.27 +null_free_domain_ssid(void *ssid)
   30.28 +{
   30.29 +    return;
   30.30 +}
   30.31 +
   30.32 +static int
   30.33 +null_dump_binary_policy(u8 *buf, u32 buf_size)
   30.34 +{ 
   30.35 +    return 0;
   30.36 +}
   30.37 +
   30.38 +static int
   30.39 +null_test_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
   30.40 +                        struct acm_sized_buffer *errors)
   30.41 +{
   30.42 +    return ACM_OK;
   30.43 +}
   30.44 +
   30.45 +static int
   30.46 +null_set_binary_policy(u8 *buf, u32 buf_size)
   30.47 +{ 
   30.48 +    return ACM_OK;
   30.49 +}
   30.50 + 
   30.51 +static int 
   30.52 +null_dump_stats(u8 *buf, u16 buf_size)
   30.53 +{
   30.54 +    /* no stats for NULL policy */
   30.55 +    return 0;
   30.56 +}
   30.57 +
   30.58 +static int
   30.59 +null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
   30.60 +{
   30.61 +    /* no types */
   30.62 +    return 0;
   30.63 +}
   30.64 +
   30.65 +
   30.66 +/* now define the hook structure similarly to LSM */
   30.67 +struct acm_operations acm_null_ops = {
   30.68 +    .init_domain_ssid = null_init_domain_ssid,
   30.69 +    .free_domain_ssid = null_free_domain_ssid,
   30.70 +    .dump_binary_policy = null_dump_binary_policy,
   30.71 +    .test_binary_policy = null_test_binary_policy,
   30.72 +    .set_binary_policy = null_set_binary_policy,
   30.73 +    .dump_statistics = null_dump_stats,
   30.74 +    .dump_ssid_types = null_dump_ssid_types,
   30.75 +    /* domain management control hooks */
   30.76 +    .domain_create = NULL,
   30.77 +    .domain_destroy = NULL,
   30.78 +    /* event channel control hooks */
   30.79 +    .pre_eventchannel_unbound = NULL,
   30.80 +    .fail_eventchannel_unbound = NULL,
   30.81 +    .pre_eventchannel_interdomain = NULL,
   30.82 +    .fail_eventchannel_interdomain = NULL,
   30.83 +    /* grant table control hooks */
   30.84 +    .pre_grant_map_ref = NULL,
   30.85 +    .fail_grant_map_ref = NULL,
   30.86 +    .pre_grant_setup = NULL,
   30.87 +    .fail_grant_setup = NULL
   30.88 +};
   30.89 +
   30.90 +/*
   30.91 + * Local variables:
   30.92 + * mode: C
   30.93 + * c-set-style: "BSD"
   30.94 + * c-basic-offset: 4
   30.95 + * tab-width: 4
   30.96 + * indent-tabs-mode: nil
   30.97 + * End:
   30.98 + */
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/xen/xsm/acm/acm_ops.c	Fri Aug 31 11:41:49 2007 +0100
    31.3 @@ -0,0 +1,212 @@
    31.4 +/******************************************************************************
    31.5 + * acm_ops.c
    31.6 + *
    31.7 + * Copyright (C) 2005 IBM Corporation
    31.8 + *
    31.9 + * Author:
   31.10 + * Reiner Sailer <sailer@watson.ibm.com>
   31.11 + *
   31.12 + * This program is free software; you can redistribute it and/or
   31.13 + * modify it under the terms of the GNU General Public License as
   31.14 + * published by the Free Software Foundation, version 2 of the
   31.15 + * License.
   31.16 + *
   31.17 + * Process acm command requests from guest OS.
   31.18 + */
   31.19 +
   31.20 +#include <xen/config.h>
   31.21 +#include <xen/types.h>
   31.22 +#include <xen/lib.h>
   31.23 +#include <xen/mm.h>
   31.24 +#include <public/acm.h>
   31.25 +#include <public/acm_ops.h>
   31.26 +#include <xen/sched.h>
   31.27 +#include <xen/event.h>
   31.28 +#include <xen/trace.h>
   31.29 +#include <xen/console.h>
   31.30 +#include <xen/guest_access.h>
   31.31 +#include <acm/acm_hooks.h>
   31.32 +
   31.33 +#ifndef ACM_SECURITY
   31.34 +
   31.35 +long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
   31.36 +{
   31.37 +    return -ENOSYS;
   31.38 +}
   31.39 +
   31.40 +#else
   31.41 +
   31.42 +int acm_authorize_acm_ops(struct domain *d)
   31.43 +{
   31.44 +    /* currently, policy management functions are restricted to privileged domains */
   31.45 +    return (IS_PRIV(d) ? 0 : -EPERM);
   31.46 +}
   31.47 +
   31.48 +
   31.49 +long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
   31.50 +{
   31.51 +    long rc = -EFAULT;
   31.52 +    struct xen_acmctl curop, *op = &curop;
   31.53 +
   31.54 +    if (acm_authorize_acm_ops(current->domain))
   31.55 +        return -EPERM;
   31.56 +
   31.57 +    if ( copy_from_guest(op, u_acmctl, 1) )
   31.58 +        return -EFAULT;
   31.59 +
   31.60 +    if (op->interface_version != ACM_INTERFACE_VERSION)
   31.61 +        return -EACCES;
   31.62 +
   31.63 +    switch ( op->cmd )
   31.64 +    {
   31.65 +
   31.66 +    case ACMOP_setpolicy: {
   31.67 +        rc = acm_set_policy(op->u.setpolicy.pushcache,
   31.68 +                            op->u.setpolicy.pushcache_size);
   31.69 +        break;
   31.70 +    }
   31.71 +
   31.72 +    case ACMOP_getpolicy: {
   31.73 +        rc = acm_get_policy(op->u.getpolicy.pullcache,
   31.74 +                            op->u.getpolicy.pullcache_size);
   31.75 +        break;
   31.76 +    }
   31.77 +
   31.78 +    case ACMOP_dumpstats: {
   31.79 +        rc = acm_dump_statistics(op->u.dumpstats.pullcache,
   31.80 +                                 op->u.dumpstats.pullcache_size);
   31.81 +        break;
   31.82 +    }
   31.83 +
   31.84 +    case ACMOP_getssid: {
   31.85 +        ssidref_t ssidref;
   31.86 +
   31.87 +        if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
   31.88 +            ssidref = op->u.getssid.id.ssidref;
   31.89 +        else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
   31.90 +        {
   31.91 +            struct domain *subj = rcu_lock_domain_by_id(op->u.getssid.id.domainid);
   31.92 +            if (!subj)
   31.93 +            {
   31.94 +                rc = -ESRCH; /* domain not found */
   31.95 +                break;
   31.96 +            }
   31.97 +            if (subj->ssid == NULL)
   31.98 +            {
   31.99 +                rcu_unlock_domain(subj);
  31.100 +                rc = -ESRCH;
  31.101 +                break;
  31.102 +            }
  31.103 +            ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
  31.104 +            rcu_unlock_domain(subj);
  31.105 +        }
  31.106 +        else
  31.107 +        {
  31.108 +            rc = -ESRCH;
  31.109 +            break;
  31.110 +        }
  31.111 +        rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
  31.112 +                          op->u.getssid.ssidbuf_size);
  31.113 +        break;
  31.114 +    }
  31.115 +
  31.116 +    case ACMOP_getdecision: {
  31.117 +        ssidref_t ssidref1, ssidref2;
  31.118 +
  31.119 +        if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
  31.120 +            ssidref1 = op->u.getdecision.id1.ssidref;
  31.121 +        else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
  31.122 +        {
  31.123 +            struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
  31.124 +            if (!subj)
  31.125 +            {
  31.126 +                rc = -ESRCH; /* domain not found */
  31.127 +                break;
  31.128 +            }
  31.129 +            if (subj->ssid == NULL)
  31.130 +            {
  31.131 +                rcu_unlock_domain(subj);
  31.132 +                rc = -ESRCH;
  31.133 +                break;
  31.134 +            }
  31.135 +            ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
  31.136 +            rcu_unlock_domain(subj);
  31.137 +        }
  31.138 +        else
  31.139 +        {
  31.140 +            rc = -ESRCH;
  31.141 +            break;
  31.142 +        }
  31.143 +        if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
  31.144 +            ssidref2 = op->u.getdecision.id2.ssidref;
  31.145 +        else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
  31.146 +        {
  31.147 +            struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
  31.148 +            if (!subj)
  31.149 +            {
  31.150 +                rc = -ESRCH; /* domain not found */
  31.151 +                break;;
  31.152 +            }
  31.153 +            if (subj->ssid == NULL)
  31.154 +            {
  31.155 +                rcu_unlock_domain(subj);
  31.156 +                rc = -ESRCH;
  31.157 +                break;
  31.158 +            }
  31.159 +            ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
  31.160 +            rcu_unlock_domain(subj);
  31.161 +        }
  31.162 +        else
  31.163 +        {
  31.164 +            rc = -ESRCH;
  31.165 +            break;
  31.166 +        }
  31.167 +        rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
  31.168 +
  31.169 +        if (rc == ACM_ACCESS_PERMITTED)
  31.170 +        {
  31.171 +            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
  31.172 +            rc = 0;
  31.173 +        }
  31.174 +        else if  (rc == ACM_ACCESS_DENIED)
  31.175 +        {
  31.176 +            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
  31.177 +            rc = 0;
  31.178 +        }
  31.179 +        else
  31.180 +            rc = -ESRCH;
  31.181 +
  31.182 +        if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
  31.183 +            rc = -EFAULT;
  31.184 +        break;
  31.185 +    }
  31.186 +
  31.187 +    case ACMOP_chgpolicy: {
  31.188 +        rc = acm_change_policy(&op->u.change_policy);
  31.189 +        break;
  31.190 +    }
  31.191 +
  31.192 +    case ACMOP_relabeldoms: {
  31.193 +        rc = acm_relabel_domains(&op->u.relabel_doms);
  31.194 +        break;
  31.195 +    }
  31.196 +
  31.197 +    default:
  31.198 +        rc = -ENOSYS;
  31.199 +        break;
  31.200 +    }
  31.201 +
  31.202 +    return rc;
  31.203 +}
  31.204 +
  31.205 +#endif
  31.206 +
  31.207 +/*
  31.208 + * Local variables:
  31.209 + * mode: C
  31.210 + * c-set-style: "BSD"
  31.211 + * c-basic-offset: 4
  31.212 + * tab-width: 4
  31.213 + * indent-tabs-mode: nil
  31.214 + * End:
  31.215 + */
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/xen/xsm/acm/acm_policy.c	Fri Aug 31 11:41:49 2007 +0100
    32.3 @@ -0,0 +1,876 @@
    32.4 +/****************************************************************
    32.5 + * acm_policy.c
    32.6 + * 
    32.7 + * Copyright (C) 2005-2007 IBM Corporation
    32.8 + *
    32.9 + * Author:
   32.10 + * Reiner Sailer <sailer@watson.ibm.com>
   32.11 + *
   32.12 + * Contributors:
   32.13 + * Stefan Berger <stefanb@watson.ibm.com>
   32.14 + *
   32.15 + * This program is free software; you can redistribute it and/or
   32.16 + * modify it under the terms of the GNU General Public License as
   32.17 + * published by the Free Software Foundation, version 2 of the
   32.18 + * License.
   32.19 + *
   32.20 + * sHype access control policy management for Xen.
   32.21 + *       This interface allows policy tools in authorized
   32.22 + *       domains to interact with the Xen access control module
   32.23 + * 
   32.24 + */
   32.25 +
   32.26 +#include <xen/config.h>
   32.27 +#include <xen/errno.h>
   32.28 +#include <xen/types.h>
   32.29 +#include <xen/lib.h>
   32.30 +#include <xen/delay.h>
   32.31 +#include <xen/sched.h>
   32.32 +#include <xen/guest_access.h>
   32.33 +#include <public/xen.h>
   32.34 +#include <acm/acm_core.h>
   32.35 +#include <public/acm_ops.h>
   32.36 +#include <acm/acm_hooks.h>
   32.37 +#include <acm/acm_endian.h>
   32.38 +#include <asm/current.h>
   32.39 +
   32.40 +static int acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
   32.41 +                                      struct acm_sized_buffer *errors);
   32.42 +static void acm_doms_change_ssidref(ssidref_t (*translator)
   32.43 +                                   (const struct acm_ssid_domain *,
   32.44 +                                    const struct acm_sized_buffer *),
   32.45 +                                    struct acm_sized_buffer *translation_map);
   32.46 +static void acm_doms_restore_ssidref(void);
   32.47 +static ssidref_t oldssid_to_newssid(const struct acm_ssid_domain *,
   32.48 +                                    const struct acm_sized_buffer *map);
   32.49 +
   32.50 +
   32.51 +int
   32.52 +acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
   32.53 +{
   32.54 +    u8 *policy_buffer = NULL;
   32.55 +    int ret = -EFAULT;
   32.56 +
   32.57 +    if ( buf_size < sizeof(struct acm_policy_buffer) )
   32.58 +        return -EFAULT;
   32.59 +
   32.60 +    /* copy buffer from guest domain */
   32.61 +    if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
   32.62 +        return -ENOMEM;
   32.63 +
   32.64 +    if ( copy_from_guest(policy_buffer, buf, buf_size) )
   32.65 +    {
   32.66 +        printk("%s: Error copying!\n",__func__);
   32.67 +        goto error_free;
   32.68 +    }
   32.69 +    ret = do_acm_set_policy(policy_buffer, buf_size, 0,
   32.70 +                            NULL, NULL, NULL);
   32.71 +
   32.72 + error_free:
   32.73 +    xfree(policy_buffer);
   32.74 +    return ret;
   32.75 +}
   32.76 +
   32.77 +
   32.78 +/*
   32.79 + * Update the policy of the running system by:
   32.80 + * - deleting ssidrefs that are not in the new policy anymore
   32.81 + *   -> no running domain may use such an ssidref
   32.82 + * - assign new ssidrefs to domains based on their old ssidrefs
   32.83 + *
   32.84 + */
   32.85 +static int
   32.86 +_acm_update_policy(void *buf, u32 buf_size, int is_bootpolicy,
   32.87 +                   struct acm_policy_buffer *pol,
   32.88 +                   struct acm_sized_buffer *deletions,
   32.89 +                   struct acm_sized_buffer *ssidchanges,
   32.90 +                   struct acm_sized_buffer *errors)
   32.91 +{
   32.92 +    uint32_t offset, length;
   32.93 +    static int require_update = 0;
   32.94 +
   32.95 +    write_lock(&acm_bin_pol_rwlock);
   32.96 +
   32.97 +    if (  require_update != 0 &&
   32.98 +        ( deletions == NULL || ssidchanges == NULL ) )
   32.99 +        goto error_lock_free;
  32.100 +
  32.101 +    require_update = 1;
  32.102 +    /*
  32.103 +       first some tests to check compatibility of new policy with
  32.104 +       current state of system/domains
  32.105 +     */
  32.106 +
  32.107 +    /* if ssidrefs are to be deleted, make sure no domain is using them */
  32.108 +    if ( deletions != NULL )
  32.109 +        if ( acm_check_deleted_ssidrefs(deletions, errors) )
  32.110 +            goto error_lock_free;
  32.111 +
  32.112 +    if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
  32.113 +        /* assign all running domains new ssidrefs as requested */
  32.114 +        acm_doms_change_ssidref(oldssid_to_newssid, ssidchanges);
  32.115 +
  32.116 +    /* test primary policy data with the new ssidrefs */
  32.117 +    offset = be32_to_cpu(pol->primary_buffer_offset);
  32.118 +    length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
  32.119 +
  32.120 +    if ( (offset + length) > buf_size ||
  32.121 +         acm_primary_ops->test_binary_policy(buf + offset, length,
  32.122 +                                             is_bootpolicy,
  32.123 +                                             errors))
  32.124 +        goto error_lock_free;
  32.125 +
  32.126 +    /* test secondary policy data with the new ssidrefs */
  32.127 +    offset = be32_to_cpu(pol->secondary_buffer_offset);
  32.128 +    length = be32_to_cpu(pol->len) - offset;
  32.129 +    if ( (offset + length) > buf_size ||
  32.130 +         acm_secondary_ops->test_binary_policy(buf + offset, length,
  32.131 +                                               is_bootpolicy,
  32.132 +                                               errors))
  32.133 +        goto error_lock_free;
  32.134 +
  32.135 +    /* end of testing --- now real updates */
  32.136 +
  32.137 +    offset = be32_to_cpu(pol->policy_reference_offset);
  32.138 +    length = be32_to_cpu(pol->primary_buffer_offset) - offset;
  32.139 +
  32.140 +    /* set label reference name */
  32.141 +    if ( (offset + length) > buf_size ||
  32.142 +         acm_set_policy_reference(buf + offset, length) )
  32.143 +        goto error_lock_free;
  32.144 +
  32.145 +    /* set primary policy data */
  32.146 +    offset = be32_to_cpu(pol->primary_buffer_offset);
  32.147 +    length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
  32.148 +
  32.149 +    if ( acm_primary_ops->set_binary_policy(buf + offset, length) )
  32.150 +        goto error_lock_free;
  32.151 +
  32.152 +    /* set secondary policy data */
  32.153 +    offset = be32_to_cpu(pol->secondary_buffer_offset);
  32.154 +    length = be32_to_cpu(pol->len) - offset;
  32.155 +    if ( acm_secondary_ops->set_binary_policy(buf + offset, length) )
  32.156 +        goto error_lock_free;
  32.157 +
  32.158 +    memcpy(&acm_bin_pol.xml_pol_version,
  32.159 +           &pol->xml_pol_version,
  32.160 +           sizeof(acm_bin_pol.xml_pol_version));
  32.161 +
  32.162 +    if ( acm_primary_ops->is_default_policy() &&
  32.163 +         acm_secondary_ops->is_default_policy() )
  32.164 +        require_update = 0;
  32.165 +
  32.166 +    write_unlock(&acm_bin_pol_rwlock);
  32.167 +
  32.168 +    return ACM_OK;
  32.169 +
  32.170 +error_lock_free:
  32.171 +    if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
  32.172 +    {
  32.173 +        acm_doms_restore_ssidref();
  32.174 +    }
  32.175 +    do_chwall_init_state_curr(NULL);
  32.176 +    write_unlock(&acm_bin_pol_rwlock);
  32.177 +
  32.178 +    return -EFAULT;
  32.179 +}
  32.180 +
  32.181 +
  32.182 +int
  32.183 +do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy,
  32.184 +                  struct acm_sized_buffer *deletions,
  32.185 +                  struct acm_sized_buffer *ssidchanges,
  32.186 +                  struct acm_sized_buffer *errors)
  32.187 +{
  32.188 +    struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
  32.189 +
  32.190 +    /* some sanity checking */
  32.191 +    if ( (be32_to_cpu(pol->magic) != ACM_MAGIC) ||
  32.192 +         (buf_size != be32_to_cpu(pol->len)) ||
  32.193 +         (be32_to_cpu(pol->policy_version) != ACM_POLICY_VERSION) )
  32.194 +    {
  32.195 +        printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
  32.196 +        goto error_free;
  32.197 +    }
  32.198 +
  32.199 +    if ( acm_active_security_policy == ACM_POLICY_UNDEFINED )
  32.200 +    {
  32.201 +        /* setup the policy with the boot policy */
  32.202 +        if ( acm_init_binary_policy(
  32.203 +                             (be32_to_cpu(pol->secondary_policy_code) << 4) |
  32.204 +                              be32_to_cpu(pol->primary_policy_code)) )
  32.205 +        {
  32.206 +            goto error_free;
  32.207 +        }
  32.208 +        acm_active_security_policy = (acm_bin_pol.secondary_policy_code << 4) |
  32.209 +                                      acm_bin_pol.primary_policy_code;
  32.210 +    }
  32.211 +
  32.212 +    /* once acm_active_security_policy is set, it cannot be changed */
  32.213 +    if ( (be32_to_cpu(pol->primary_policy_code) !=
  32.214 +                                        acm_bin_pol.primary_policy_code) ||
  32.215 +         (be32_to_cpu(pol->secondary_policy_code) !=
  32.216 +                                        acm_bin_pol.secondary_policy_code) )
  32.217 +    {
  32.218 +        printkd("%s: Wrong policy type in boot policy!\n", __func__);
  32.219 +        goto error_free;
  32.220 +    }
  32.221 +
  32.222 +    return _acm_update_policy(buf, buf_size, is_bootpolicy,
  32.223 +                              pol,
  32.224 +                              deletions, ssidchanges,
  32.225 +                              errors);
  32.226 +
  32.227 + error_free:
  32.228 +    printk("%s: Error setting policy.\n", __func__);
  32.229 +    return -EFAULT;
  32.230 +}
  32.231 +
  32.232 +int
  32.233 +acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
  32.234 +{ 
  32.235 +    u8 *policy_buffer;
  32.236 +    int ret;
  32.237 +    struct acm_policy_buffer *bin_pol;
  32.238 +
  32.239 +    if ( buf_size < sizeof(struct acm_policy_buffer) )
  32.240 +        return -EFAULT;
  32.241 +
  32.242 +    if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
  32.243 +        return -ENOMEM;
  32.244 +
  32.245 +    read_lock(&acm_bin_pol_rwlock);
  32.246 +
  32.247 +    bin_pol = (struct acm_policy_buffer *)policy_buffer;
  32.248 +    bin_pol->magic = cpu_to_be32(ACM_MAGIC);
  32.249 +    bin_pol->primary_policy_code =
  32.250 +                                cpu_to_be32(acm_bin_pol.primary_policy_code);
  32.251 +    bin_pol->secondary_policy_code =
  32.252 +                                cpu_to_be32(acm_bin_pol.secondary_policy_code);
  32.253 +
  32.254 +    bin_pol->len = cpu_to_be32(sizeof(struct acm_policy_buffer));
  32.255 +    bin_pol->policy_reference_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  32.256 +    bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  32.257 +    bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  32.258 +
  32.259 +    memcpy(&bin_pol->xml_pol_version,
  32.260 +           &acm_bin_pol.xml_pol_version,
  32.261 +           sizeof(struct acm_policy_version));
  32.262 +
  32.263 +    ret = acm_dump_policy_reference(
  32.264 +               policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset),
  32.265 +               buf_size - be32_to_cpu(bin_pol->policy_reference_offset));
  32.266 +
  32.267 +    if ( ret < 0 )
  32.268 +        goto error_free_unlock;
  32.269 +
  32.270 +    bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
  32.271 +    bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  32.272 +
  32.273 +    ret = acm_primary_ops->dump_binary_policy(
  32.274 +                 policy_buffer + be32_to_cpu(bin_pol->primary_buffer_offset),
  32.275 +                 buf_size - be32_to_cpu(bin_pol->primary_buffer_offset));
  32.276 +
  32.277 +    if ( ret < 0 )
  32.278 +        goto error_free_unlock;
  32.279 +
  32.280 +    bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
  32.281 +    bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
  32.282 +
  32.283 +    ret = acm_secondary_ops->dump_binary_policy(
  32.284 +               policy_buffer + be32_to_cpu(bin_pol->secondary_buffer_offset),
  32.285 +               buf_size - be32_to_cpu(bin_pol->secondary_buffer_offset));
  32.286 +
  32.287 +    if ( ret < 0 )
  32.288 +        goto error_free_unlock;
  32.289 +
  32.290 +    bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
  32.291 +    if ( copy_to_guest(buf, policy_buffer, be32_to_cpu(bin_pol->len)) )
  32.292 +        goto error_free_unlock;
  32.293 +
  32.294 +    read_unlock(&acm_bin_pol_rwlock);
  32.295 +    xfree(policy_buffer);
  32.296 +
  32.297 +    return ACM_OK;
  32.298 +
  32.299 + error_free_unlock:
  32.300 +    read_unlock(&acm_bin_pol_rwlock);
  32.301 +    printk("%s: Error getting policy.\n", __func__);
  32.302 +    xfree(policy_buffer);
  32.303 +
  32.304 +    return -EFAULT;
  32.305 +}
  32.306 +
  32.307 +int
  32.308 +acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
  32.309 +{ 
  32.310 +    /* send stats to user space */
  32.311 +    u8 *stats_buffer;
  32.312 +    int len1, len2;
  32.313 +    struct acm_stats_buffer acm_stats;
  32.314 +
  32.315 +    if ( (stats_buffer = xmalloc_array(u8, buf_size)) == NULL )
  32.316 +        return -ENOMEM;
  32.317 +
  32.318 +    read_lock(&acm_bin_pol_rwlock);
  32.319 +     
  32.320 +    len1 = acm_primary_ops->dump_statistics(
  32.321 +                             stats_buffer + sizeof(struct acm_stats_buffer),
  32.322 +                             buf_size - sizeof(struct acm_stats_buffer));
  32.323 +    if ( len1 < 0 )
  32.324 +        goto error_lock_free;
  32.325 +      
  32.326 +    len2 = acm_secondary_ops->dump_statistics(
  32.327 +                      stats_buffer + sizeof(struct acm_stats_buffer) + len1,
  32.328 +                      buf_size - sizeof(struct acm_stats_buffer) - len1);
  32.329 +    if ( len2 < 0 )
  32.330 +        goto error_lock_free;
  32.331 +
  32.332 +    acm_stats.magic = cpu_to_be32(ACM_MAGIC);
  32.333 +    acm_stats.primary_policy_code =
  32.334 +                           cpu_to_be32(acm_bin_pol.primary_policy_code);
  32.335 +    acm_stats.secondary_policy_code =
  32.336 +                           cpu_to_be32(acm_bin_pol.secondary_policy_code);
  32.337 +    acm_stats.primary_stats_offset =
  32.338 +                           cpu_to_be32(sizeof(struct acm_stats_buffer));
  32.339 +    acm_stats.secondary_stats_offset =
  32.340 +                           cpu_to_be32(sizeof(struct acm_stats_buffer) + len1);
  32.341 +    acm_stats.len = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1 + len2);
  32.342 +
  32.343 +    memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
  32.344 +
  32.345 +    if ( copy_to_guest(buf,
  32.346 +                       stats_buffer,
  32.347 +                       sizeof(struct acm_stats_buffer) + len1 + len2) )
  32.348 +        goto error_lock_free;
  32.349 +
  32.350 +    read_unlock(&acm_bin_pol_rwlock);
  32.351 +    xfree(stats_buffer);
  32.352 +
  32.353 +    return ACM_OK;
  32.354 +
  32.355 + error_lock_free:
  32.356 +    read_unlock(&acm_bin_pol_rwlock);
  32.357 +    xfree(stats_buffer);
  32.358 +
  32.359 +    return -EFAULT;
  32.360 +}
  32.361 +
  32.362 +
  32.363 +int
  32.364 +acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
  32.365 +{
  32.366 +    /* send stats to user space */
  32.367 +    u8 *ssid_buffer;
  32.368 +    int ret;
  32.369 +    struct acm_ssid_buffer *acm_ssid;
  32.370 +    if ( buf_size < sizeof(struct acm_ssid_buffer) )
  32.371 +        return -EFAULT;
  32.372 +
  32.373 +    if ( (ssid_buffer = xmalloc_array(u8, buf_size)) == NULL )
  32.374 +        return -ENOMEM;
  32.375 +
  32.376 +    read_lock(&acm_bin_pol_rwlock);
  32.377 +
  32.378 +    acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
  32.379 +    acm_ssid->len = sizeof(struct acm_ssid_buffer);
  32.380 +    acm_ssid->ssidref = ssidref;
  32.381 +    acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
  32.382 +    acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
  32.383 +
  32.384 +    acm_ssid->policy_reference_offset = acm_ssid->len;
  32.385 +    ret = acm_dump_policy_reference(
  32.386 +                          ssid_buffer + acm_ssid->policy_reference_offset,
  32.387 +                          buf_size - acm_ssid->policy_reference_offset);
  32.388 +    if ( ret < 0 )
  32.389 +        goto error_free_unlock;
  32.390 +
  32.391 +    acm_ssid->len += ret;
  32.392 +    acm_ssid->primary_types_offset = acm_ssid->len;
  32.393 +
  32.394 +    /* ret >= 0 --> ret == max_types */
  32.395 +    ret = acm_primary_ops->dump_ssid_types(
  32.396 +                                 ACM_PRIMARY(ssidref),
  32.397 +                                 ssid_buffer + acm_ssid->primary_types_offset,
  32.398 +                                 buf_size - acm_ssid->primary_types_offset);
  32.399 +    if ( ret < 0 )
  32.400 +        goto error_free_unlock;
  32.401 +
  32.402 +    acm_ssid->len += ret;
  32.403 +    acm_ssid->primary_max_types = ret;
  32.404 +    acm_ssid->secondary_types_offset = acm_ssid->len;
  32.405 +
  32.406 +    ret = acm_secondary_ops->dump_ssid_types(
  32.407 +                             ACM_SECONDARY(ssidref),
  32.408 +                             ssid_buffer + acm_ssid->secondary_types_offset,
  32.409 +                             buf_size - acm_ssid->secondary_types_offset);
  32.410 +    if ( ret < 0 )
  32.411 +        goto error_free_unlock;
  32.412 +
  32.413 +    acm_ssid->len += ret;
  32.414 +    acm_ssid->secondary_max_types = ret;
  32.415 +
  32.416 +    if ( copy_to_guest(buf, ssid_buffer, acm_ssid->len) )
  32.417 +        goto error_free_unlock;
  32.418 +
  32.419 +    read_unlock(&acm_bin_pol_rwlock);
  32.420 +    xfree(ssid_buffer);
  32.421 +
  32.422 +    return ACM_OK;
  32.423 +
  32.424 + error_free_unlock:
  32.425 +    read_unlock(&acm_bin_pol_rwlock);
  32.426 +    printk("%s: Error getting ssid.\n", __func__);
  32.427 +    xfree(ssid_buffer);
  32.428 +
  32.429 +    return -ENOMEM;
  32.430 +}
  32.431 +
  32.432 +int
  32.433 +acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook)
  32.434 +{
  32.435 +    int ret = ACM_ACCESS_DENIED;
  32.436 +    switch ( hook )
  32.437 +    {
  32.438 +
  32.439 +    case ACMHOOK_sharing:
  32.440 +        /* Sharing hook restricts access in STE policy only */
  32.441 +        ret = acm_sharing(ssidref1, ssidref2);
  32.442 +        break;
  32.443 +
  32.444 +    case ACMHOOK_authorization:
  32.445 +        ret = acm_authorization(ssidref1, ssidref2);
  32.446 +        break;
  32.447 +
  32.448 +    default:
  32.449 +        /* deny */
  32.450 +        break;
  32.451 +    }
  32.452 +
  32.453 +    printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n",
  32.454 +            __func__, ssidref1, ssidref2,
  32.455 +            (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED");
  32.456 +
  32.457 +    return ret;
  32.458 +}
  32.459 +
  32.460 +
  32.461 +
  32.462 +/*
  32.463 +   Check if an ssidref of the current policy type is being used by any
  32.464 +   domain.
  32.465 + */
  32.466 +static int
  32.467 +acm_check_used_ssidref(uint32_t policy_type, uint32_t search_ssidref,
  32.468 +                       struct acm_sized_buffer *errors)
  32.469 +{
  32.470 +    int rc = 0;
  32.471 +    struct acm_ssid_domain *rawssid;
  32.472 +
  32.473 +    read_lock(&ssid_list_rwlock);
  32.474 +
  32.475 +    for_each_acmssid( rawssid )
  32.476 +    {
  32.477 +        ssidref_t ssidref;
  32.478 +        void *s = GET_SSIDP(policy_type, rawssid);
  32.479 +
  32.480 +        if ( policy_type == ACM_CHINESE_WALL_POLICY )
  32.481 +        {
  32.482 +            ssidref = ((struct chwall_ssid *)s)->chwall_ssidref;
  32.483 +        } else {
  32.484 +            ssidref = ((struct ste_ssid *)s)->ste_ssidref;
  32.485 +        }
  32.486 +        gdprintk(XENLOG_INFO,"domid=%d: search ssidref=%d, ssidref=%d\n",
  32.487 +                 rawssid->domainid,search_ssidref,ssidref);
  32.488 +        if ( ssidref == search_ssidref )
  32.489 +        {
  32.490 +            /* one is enough */
  32.491 +            acm_array_append_tuple(errors, ACM_SSIDREF_IN_USE, search_ssidref);
  32.492 +            rc = 1;
  32.493 +            break;
  32.494 +        }
  32.495 +    }
  32.496 +
  32.497 +    read_unlock(&ssid_list_rwlock);
  32.498 +
  32.499 +    return rc;
  32.500 +}
  32.501 +
  32.502 +
  32.503 +/*
  32.504 + * Translate a current ssidref into its future representation under
  32.505 + * the new policy.
  32.506 + * The map provides translation of ssidrefs from old to new in tuples
  32.507 + * of (old ssidref, new ssidref).
  32.508 + */
  32.509 +static ssidref_t
  32.510 +oldssid_to_newssid(const struct acm_ssid_domain *rawssid,
  32.511 +                   const struct acm_sized_buffer *map)
  32.512 +{
  32.513 +    uint i;
  32.514 +
  32.515 +    if ( rawssid != NULL )
  32.516 +    {
  32.517 +        ssidref_t ssid = rawssid->ssidref & 0xffff;
  32.518 +        for ( i = 0; i + 1 < map->num_items; i += 2 )
  32.519 +        {
  32.520 +            if ( map->array[i] == ssid )
  32.521 +            {
  32.522 +                return (map->array[i+1] << 16 | map->array[i+1]);
  32.523 +            }
  32.524 +        }
  32.525 +    }
  32.526 +    return ACM_INVALID_SSIDREF;
  32.527 +}
  32.528 +
  32.529 +
  32.530 +/*
  32.531 + * Assign an ssidref to the CHWALL policy component of the domain
  32.532 + */
  32.533 +static void
  32.534 +acm_pri_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
  32.535 +                              ssidref_t new_ssid)
  32.536 +{
  32.537 +    struct chwall_ssid *chwall = (struct chwall_ssid *)rawssid->primary_ssid;
  32.538 +    chwall->chwall_ssidref = new_ssid;
  32.539 +}
  32.540 +
  32.541 +
  32.542 +/*
  32.543 + * Assign an ssidref to the STE policy component of the domain
  32.544 + */
  32.545 +static void
  32.546 +acm_sec_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
  32.547 +                              ssidref_t new_ssid)
  32.548 +{
  32.549 +    struct ste_ssid *ste = (struct ste_ssid *)rawssid->secondary_ssid;
  32.550 +    ste->ste_ssidref = new_ssid;
  32.551 +}
  32.552 +
  32.553 +/*
  32.554 +   Change the ssidrefs on each domain using a passed translation function;
  32.555 + */
  32.556 +static void
  32.557 +acm_doms_change_ssidref(ssidref_t (*translator_fn)
  32.558 +                          (const struct acm_ssid_domain *,
  32.559 +                           const struct acm_sized_buffer *),
  32.560 +                        struct acm_sized_buffer *translation_map)
  32.561 +{
  32.562 +    struct acm_ssid_domain *rawssid;
  32.563 +
  32.564 +    write_lock(&ssid_list_rwlock);
  32.565 +
  32.566 +    for_each_acmssid( rawssid )
  32.567 +    {
  32.568 +        ssidref_t new_ssid;
  32.569 +
  32.570 +        rawssid->old_ssidref = rawssid->ssidref;
  32.571 +
  32.572 +        new_ssid = translator_fn(rawssid, translation_map);
  32.573 +        if ( new_ssid == ACM_INVALID_SSIDREF )
  32.574 +        {
  32.575 +            /* means no mapping found, so no change -- old = new */
  32.576 +            continue;
  32.577 +        }
  32.578 +
  32.579 +        acm_pri_policy_assign_ssidref(rawssid, ACM_PRIMARY  (new_ssid) );
  32.580 +        acm_sec_policy_assign_ssidref(rawssid, ACM_SECONDARY(new_ssid) );
  32.581 +
  32.582 +        rawssid->ssidref = new_ssid;
  32.583 +    }
  32.584 +
  32.585 +    write_unlock(&ssid_list_rwlock);
  32.586 +}
  32.587 +
  32.588 +/*
  32.589 + * Restore the previous ssidref values on all domains
  32.590 + */
  32.591 +static void
  32.592 +acm_doms_restore_ssidref(void)
  32.593 +{
  32.594 +    struct acm_ssid_domain *rawssid;
  32.595 +
  32.596 +    write_lock(&ssid_list_rwlock);
  32.597 +
  32.598 +    for_each_acmssid( rawssid )
  32.599 +    {
  32.600 +        ssidref_t old_ssid;
  32.601 +
  32.602 +        if ( rawssid->old_ssidref == rawssid->ssidref )
  32.603 +            continue;
  32.604 +
  32.605 +        old_ssid = rawssid->old_ssidref & 0xffff;
  32.606 +        rawssid->ssidref = rawssid->old_ssidref;
  32.607 +
  32.608 +        acm_pri_policy_assign_ssidref(rawssid, old_ssid);
  32.609 +        acm_sec_policy_assign_ssidref(rawssid, old_ssid);
  32.610 +    }
  32.611 +
  32.612 +    write_unlock(&ssid_list_rwlock);
  32.613 +}
  32.614 +
  32.615 +
  32.616 +/*
  32.617 +   Check the list of domains whether either one of them uses a
  32.618 +   to-be-deleted ssidref.
  32.619 + */
  32.620 +static int
  32.621 +acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
  32.622 +                           struct acm_sized_buffer *errors)
  32.623 +{
  32.624 +    int rc = 0;
  32.625 +    uint idx;
  32.626 +    /* check for running domains that should not be there anymore */
  32.627 +    for ( idx = 0; idx < dels->num_items; idx++ )
  32.628 +    {
  32.629 +        if ( acm_check_used_ssidref(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  32.630 +                                    dels->array[idx],
  32.631 +                                    errors) > 0 ||
  32.632 +             acm_check_used_ssidref(ACM_CHINESE_WALL_POLICY,
  32.633 +                                    dels->array[idx],
  32.634 +                                    errors) > 0)
  32.635 +        {
  32.636 +            rc = ACM_ERROR;
  32.637 +            break;
  32.638 +        }
  32.639 +    }
  32.640 +    return rc;
  32.641 +}
  32.642 +
  32.643 +
  32.644 +/*
  32.645 + * Change the policy of the system.
  32.646 + */
  32.647 +int
  32.648 +acm_change_policy(struct acm_change_policy *chgpolicy)
  32.649 +{
  32.650 +    int rc = 0;
  32.651 +    u8 *binpolicy = NULL;
  32.652 +    struct acm_sized_buffer dels =
  32.653 +    {
  32.654 +        .array = NULL,
  32.655 +    };
  32.656 +    struct acm_sized_buffer ssidmap =
  32.657 +    {
  32.658 +        .array = NULL,
  32.659 +    };
  32.660 +    struct acm_sized_buffer errors =
  32.661 +    {
  32.662 +        .array = NULL,
  32.663 +    };
  32.664 +
  32.665 +    gdprintk(XENLOG_INFO, "change policy operation\n");
  32.666 +
  32.667 +    if ( (chgpolicy->delarray_size > 4096) ||
  32.668 +         (chgpolicy->chgarray_size > 4096) ||
  32.669 +         (chgpolicy->errarray_size > 4096))
  32.670 +    {
  32.671 +        return ACM_ERROR;
  32.672 +    }
  32.673 +
  32.674 +    dels.num_items = chgpolicy->delarray_size / sizeof(uint32_t);
  32.675 +    if ( dels.num_items > 0 )
  32.676 +    {
  32.677 +        dels.array = xmalloc_array(uint32_t, dels.num_items);
  32.678 +        if ( dels.array == NULL )
  32.679 +        {
  32.680 +            rc = -ENOMEM;
  32.681 +            goto acm_chg_policy_exit;
  32.682 +        }
  32.683 +    }
  32.684 +
  32.685 +    ssidmap.num_items = chgpolicy->chgarray_size / sizeof(uint32_t);
  32.686 +    if ( ssidmap.num_items > 0 )
  32.687 +    {
  32.688 +        ssidmap.array = xmalloc_array(uint32_t, ssidmap.num_items);
  32.689 +        if ( ssidmap.array == NULL )
  32.690 +        {
  32.691 +            rc = -ENOMEM;
  32.692 +            goto acm_chg_policy_exit;
  32.693 +        }
  32.694 +    }
  32.695 +
  32.696 +    errors.num_items = chgpolicy->errarray_size / sizeof(uint32_t);
  32.697 +    if ( errors.num_items > 0 )
  32.698 +    {
  32.699 +        errors.array = xmalloc_array(uint32_t, errors.num_items);
  32.700 +        if ( errors.array == NULL )
  32.701 +        {
  32.702 +            rc = -ENOMEM;
  32.703 +            goto acm_chg_policy_exit;
  32.704 +        }
  32.705 +        memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
  32.706 +    }
  32.707 +
  32.708 +    binpolicy = xmalloc_array(u8,
  32.709 +                              chgpolicy->policy_pushcache_size);
  32.710 +    if ( binpolicy == NULL )
  32.711 +    {
  32.712 +        rc = -ENOMEM;
  32.713 +        goto acm_chg_policy_exit;
  32.714 +    }
  32.715 +
  32.716 +    if ( copy_from_guest(dels.array,
  32.717 +                         chgpolicy->del_array,
  32.718 +                         dels.num_items) ||
  32.719 +         copy_from_guest(ssidmap.array,
  32.720 +                         chgpolicy->chg_array,
  32.721 +                         ssidmap.num_items) ||
  32.722 +         copy_from_guest(binpolicy,
  32.723 +                         chgpolicy->policy_pushcache,
  32.724 +                         chgpolicy->policy_pushcache_size ))
  32.725 +    {
  32.726 +        rc = -EFAULT;
  32.727 +        goto acm_chg_policy_exit;
  32.728 +    }
  32.729 +
  32.730 +    rc = do_acm_set_policy(binpolicy,
  32.731 +                           chgpolicy->policy_pushcache_size,
  32.732 +                           0,
  32.733 +                           &dels, &ssidmap, &errors);
  32.734 +
  32.735 +    if ( (errors.num_items > 0) &&
  32.736 +         copy_to_guest(chgpolicy->err_array,
  32.737 +                       errors.array,
  32.738 +                       errors.num_items ) )
  32.739 +    {
  32.740 +        rc = -EFAULT;
  32.741 +        goto acm_chg_policy_exit;
  32.742 +    }
  32.743 +
  32.744 +
  32.745 +acm_chg_policy_exit:
  32.746 +    xfree(dels.array);
  32.747 +    xfree(ssidmap.array);
  32.748 +    xfree(errors.array);
  32.749 +    xfree(binpolicy);
  32.750 +
  32.751 +    return rc;
  32.752 +}
  32.753 +
  32.754 +
  32.755 +/*
  32.756 + * Lookup the new ssidref given the domain's id.
  32.757 + * The translation map provides a list of tuples in the format
  32.758 + * (domid, new ssidref).
  32.759 + */
  32.760 +static ssidref_t
  32.761 +domid_to_newssid(const struct acm_ssid_domain *rawssid,
  32.762 +                 const struct acm_sized_buffer *map)
  32.763 +{
  32.764 +    domid_t domid = rawssid->domainid;
  32.765 +    uint i;
  32.766 +    for ( i = 0; (i+1) < map->num_items; i += 2 )
  32.767 +    {
  32.768 +        if ( map->array[i] == domid )
  32.769 +            return (ssidref_t)map->array[i+1];
  32.770 +    }
  32.771 +    return ACM_INVALID_SSIDREF;
  32.772 +}
  32.773 +
  32.774 +
  32.775 +int
  32.776 +do_acm_relabel_doms(struct acm_sized_buffer *relabel_map,
  32.777 +                    struct acm_sized_buffer *errors)
  32.778 +{
  32.779 +    int rc = 0, irc;
  32.780 +
  32.781 +    write_lock(&acm_bin_pol_rwlock);
  32.782 +
  32.783 +    acm_doms_change_ssidref(domid_to_newssid, relabel_map);
  32.784 +
  32.785 +    /* run tests; collect as much error info as possible */
  32.786 +    irc =  do_chwall_init_state_curr(errors);
  32.787 +    irc += do_ste_init_state_curr(errors);
  32.788 +    if ( irc != 0 )
  32.789 +    {
  32.790 +        rc = -EFAULT;
  32.791 +        goto acm_relabel_doms_lock_err_exit;
  32.792 +    }
  32.793 +
  32.794 +    write_unlock(&acm_bin_pol_rwlock);
  32.795 +
  32.796 +    return rc;
  32.797 +
  32.798 +acm_relabel_doms_lock_err_exit:
  32.799 +    /* revert the new ssidref assignment */
  32.800 +    acm_doms_restore_ssidref();
  32.801 +    do_chwall_init_state_curr(NULL);
  32.802 +
  32.803 +    write_unlock(&acm_bin_pol_rwlock);
  32.804 +
  32.805 +    return rc;
  32.806 +}
  32.807 +
  32.808 +
  32.809 +int
  32.810 +acm_relabel_domains(struct acm_relabel_doms *relabel)
  32.811 +{
  32.812 +    int rc = ACM_OK;
  32.813 +    struct acm_sized_buffer relabels =
  32.814 +    {
  32.815 +        .array = NULL,
  32.816 +    };
  32.817 +    struct acm_sized_buffer errors =
  32.818 +    {
  32.819 +        .array = NULL,
  32.820 +    };
  32.821 +
  32.822 +    if ( relabel->relabel_map_size > 4096 )
  32.823 +    {
  32.824 +        return ACM_ERROR;
  32.825 +    }
  32.826 +
  32.827 +    relabels.num_items = relabel->relabel_map_size / sizeof(uint32_t);
  32.828 +    if ( relabels.num_items > 0 )
  32.829 +    {
  32.830 +        relabels.array = xmalloc_array(uint32_t, relabels.num_items);
  32.831 +        if ( relabels.array == NULL )
  32.832 +        {
  32.833 +            rc = -ENOMEM;
  32.834 +            goto acm_relabel_doms_exit;
  32.835 +        }
  32.836 +    }
  32.837 +
  32.838 +    errors.num_items = relabel->errarray_size / sizeof(uint32_t);
  32.839 +    if ( errors.num_items > 0 )
  32.840 +    {
  32.841 +        errors.array = xmalloc_array(uint32_t, errors.num_items);
  32.842 +        if ( errors.array == NULL )
  32.843 +        {
  32.844 +            rc = -ENOMEM;
  32.845 +            goto acm_relabel_doms_exit;
  32.846 +        }
  32.847 +        memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
  32.848 +    }
  32.849 +
  32.850 +    if ( copy_from_guest(relabels.array,
  32.851 +                         relabel->relabel_map,
  32.852 +                         relabels.num_items) )
  32.853 +    {
  32.854 +        rc = -EFAULT;
  32.855 +        goto acm_relabel_doms_exit;
  32.856 +    }
  32.857 +
  32.858 +    rc = do_acm_relabel_doms(&relabels, &errors);
  32.859 +
  32.860 +    if ( copy_to_guest(relabel->err_array,
  32.861 +                       errors.array,
  32.862 +                       errors.num_items ) )
  32.863 +        rc = -EFAULT;
  32.864 +
  32.865 +acm_relabel_doms_exit:
  32.866 +    xfree(relabels.array);
  32.867 +    xfree(errors.array);
  32.868 +    return rc;
  32.869 +}
  32.870 +
  32.871 +/*
  32.872 + * Local variables:
  32.873 + * mode: C
  32.874 + * c-set-style: "BSD"
  32.875 + * c-basic-offset: 4
  32.876 + * tab-width: 4
  32.877 + * indent-tabs-mode: nil
  32.878 + * End:
  32.879 + */
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c	Fri Aug 31 11:41:49 2007 +0100
    33.3 @@ -0,0 +1,914 @@
    33.4 +/****************************************************************
    33.5 + * acm_simple_type_enforcement_hooks.c
    33.6 + * 
    33.7 + * Copyright (C) 2005 IBM Corporation
    33.8 + *
    33.9 + * Author:
   33.10 + * Reiner Sailer <sailer@watson.ibm.com>
   33.11 + *
   33.12 + * Contributors:
   33.13 + * Stefan Berger <stefanb@watson.ibm.com>
   33.14 + *         support for network order binary policies
   33.15 + *
   33.16 + * This program is free software; you can redistribute it and/or
   33.17 + * modify it under the terms of the GNU General Public License as
   33.18 + * published by the Free Software Foundation, version 2 of the
   33.19 + * License.
   33.20 + *
   33.21 + * sHype Simple Type Enforcement for Xen
   33.22 + *     STE allows to control which domains can setup sharing
   33.23 + *     (eventchannels right now) with which other domains. Hooks
   33.24 + *     are defined and called throughout Xen when domains bind to
   33.25 + *     shared resources (setup eventchannels) and a domain is allowed
   33.26 + *     to setup sharing with another domain if and only if both domains
   33.27 + *     share at least on common type.
   33.28 + *
   33.29 + */
   33.30 +
   33.31 +#include <xen/lib.h>
   33.32 +#include <asm/types.h>
   33.33 +#include <asm/current.h>
   33.34 +#include <acm/acm_hooks.h>
   33.35 +#include <asm/atomic.h>
   33.36 +#include <acm/acm_endian.h>
   33.37 +#include <acm/acm_core.h>
   33.38 +
   33.39 +ssidref_t dom0_ste_ssidref = 0x0001;
   33.40 +
   33.41 +/* local cache structures for STE policy */
   33.42 +struct ste_binary_policy ste_bin_pol;
   33.43 +
   33.44 +static inline int have_common_type (ssidref_t ref1, ssidref_t ref2)
   33.45 +{
   33.46 +    int i;
   33.47 +
   33.48 +    if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
   33.49 +         ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
   33.50 +    {
   33.51 +        for( i = 0; i< ste_bin_pol.max_types; i++ )
   33.52 +            if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
   33.53 +                 ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
   33.54 +            {
   33.55 +                printkd("%s: common type #%02x.\n", __func__, i);
   33.56 +                return 1;
   33.57 +            }
   33.58 +    }
   33.59 +    return 0;
   33.60 +}
   33.61 +
   33.62 +static inline int is_superset(ssidref_t ref1, ssidref_t ref2)
   33.63 +{
   33.64 +    int i;
   33.65 +
   33.66 +    if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
   33.67 +         ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
   33.68 +    {
   33.69 +        for( i = 0; i< ste_bin_pol.max_types; i++ )
   33.70 +            if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
   33.71 +                 ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
   33.72 +            {
   33.73 +                return 0;
   33.74 +            }
   33.75 +    } else {
   33.76 +        return 0;
   33.77 +    }
   33.78 +    return 1;
   33.79 +}
   33.80 +
   33.81 +
   33.82 +/* Helper function: return = (subj and obj share a common type) */
   33.83 +static int share_common_type(struct domain *subj, struct domain *obj)
   33.84 +{
   33.85 +    ssidref_t ref_s, ref_o;
   33.86 +    int ret;
   33.87 +
   33.88 +    if ( (subj == NULL) || (obj == NULL) ||
   33.89 +         (subj->ssid == NULL) || (obj->ssid == NULL) )
   33.90 +        return 0;
   33.91 +
   33.92 +    read_lock(&acm_bin_pol_rwlock);
   33.93 +
   33.94 +    /* lookup the policy-local ssids */
   33.95 +    ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
   33.96 +                       (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
   33.97 +    ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
   33.98 +                       (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
   33.99 +    /* check whether subj and obj share a common ste type */
  33.100 +    ret = have_common_type(ref_s, ref_o);
  33.101 +
  33.102 +    read_unlock(&acm_bin_pol_rwlock);
  33.103 +
  33.104 +    return ret;
  33.105 +}
  33.106 +
  33.107 +/*
  33.108 + * Initializing STE policy (will be filled by policy partition
  33.109 + * using setpolicy command)
  33.110 + */
  33.111 +int acm_init_ste_policy(void)
  33.112 +{
  33.113 +    /* minimal startup policy; policy write-locked already */
  33.114 +    ste_bin_pol.max_types = 1;
  33.115 +    ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref;
  33.116 +    ste_bin_pol.ssidrefs =
  33.117 +            (domaintype_t *)xmalloc_array(domaintype_t,
  33.118 +                                          ste_bin_pol.max_types *
  33.119 +                                          ste_bin_pol.max_ssidrefs);
  33.120 +
  33.121 +    if (ste_bin_pol.ssidrefs == NULL)
  33.122 +        return ACM_INIT_SSID_ERROR;
  33.123 +
  33.124 +    memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) *
  33.125 +                                    ste_bin_pol.max_types *
  33.126 +                                    ste_bin_pol.max_ssidrefs);
  33.127 +
  33.128 +    /* initialize state so that dom0 can start up and communicate with itself */
  33.129 +    ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1;
  33.130 +
  33.131 +    /* init stats */
  33.132 +    atomic_set(&(ste_bin_pol.ec_eval_count), 0);
  33.133 +    atomic_set(&(ste_bin_pol.ec_denied_count), 0);
  33.134 +    atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
  33.135 +    atomic_set(&(ste_bin_pol.gt_eval_count), 0);
  33.136 +    atomic_set(&(ste_bin_pol.gt_denied_count), 0);
  33.137 +    atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
  33.138 +
  33.139 +    return ACM_OK;
  33.140 +}
  33.141 +
  33.142 +
  33.143 +/* ste initialization function hooks */
  33.144 +static int
  33.145 +ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
  33.146 +{
  33.147 +    int i;
  33.148 +    struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
  33.149 +
  33.150 +    if ( ste_ssidp == NULL )
  33.151 +        return ACM_INIT_SSID_ERROR;
  33.152 +
  33.153 +    /* get policy-local ssid reference */
  33.154 +    ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  33.155 +                                         ssidref);
  33.156 +
  33.157 +    if ( (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) )
  33.158 +    {
  33.159 +        printkd("%s: ERROR ste_ssidref (%x) undefined or unset (0).\n",
  33.160 +                __func__, ste_ssidp->ste_ssidref);
  33.161 +        xfree(ste_ssidp);
  33.162 +        return ACM_INIT_SSID_ERROR;
  33.163 +    }
  33.164 +    /* clean ste cache */
  33.165 +    for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  33.166 +        ste_ssidp->ste_cache[i].valid = ACM_STE_free;
  33.167 +
  33.168 +    (*ste_ssid) = ste_ssidp;
  33.169 +    printkd("%s: determined ste_ssidref to %x.\n", 
  33.170 +            __func__, ste_ssidp->ste_ssidref);
  33.171 +
  33.172 +    return ACM_OK;
  33.173 +}
  33.174 +
  33.175 +
  33.176 +static void
  33.177 +ste_free_domain_ssid(void *ste_ssid)
  33.178 +{
  33.179 +    xfree(ste_ssid);
  33.180 +    return;
  33.181 +}
  33.182 +
  33.183 +/* dump type enforcement cache; policy read-locked already */
  33.184 +static int 
  33.185 +ste_dump_policy(u8 *buf, u32 buf_size) {
  33.186 +    struct acm_ste_policy_buffer *ste_buf =
  33.187 +                                  (struct acm_ste_policy_buffer *)buf;
  33.188 +    int ret = 0;
  33.189 +
  33.190 +    if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
  33.191 +        return -EINVAL;
  33.192 +
  33.193 +    ste_buf->ste_max_types = cpu_to_be32(ste_bin_pol.max_types);
  33.194 +    ste_buf->ste_max_ssidrefs = cpu_to_be32(ste_bin_pol.max_ssidrefs);
  33.195 +    ste_buf->policy_code = cpu_to_be32(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
  33.196 +    ste_buf->ste_ssid_offset =
  33.197 +                           cpu_to_be32(sizeof(struct acm_ste_policy_buffer));
  33.198 +    ret = be32_to_cpu(ste_buf->ste_ssid_offset) +
  33.199 +        sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
  33.200 +
  33.201 +    ret = (ret + 7) & ~7;
  33.202 +
  33.203 +    if (buf_size < ret)
  33.204 +        return -EINVAL;
  33.205 +
  33.206 +    /* now copy buffer over */
  33.207 +    arrcpy(buf + be32_to_cpu(ste_buf->ste_ssid_offset),
  33.208 +           ste_bin_pol.ssidrefs,
  33.209 +           sizeof(domaintype_t),
  33.210 +           ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
  33.211 +
  33.212 +    return ret;
  33.213 +}
  33.214 +
  33.215 +/*
  33.216 + * ste_init_state is called when a policy is changed to detect violations
  33.217 + * (return != 0). from a security point of view, we simulate that all
  33.218 + * running domains are re-started and all sharing decisions are replayed
  33.219 + * to detect violations or current sharing behavior (right now:
  33.220 + * event_channels, future: also grant_tables)
  33.221 + */ 
  33.222 +static int
  33.223 +ste_init_state(struct acm_sized_buffer *errors)
  33.224 +{
  33.225 +    int violation = 1;
  33.226 +    struct ste_ssid *ste_ssid, *ste_rssid;
  33.227 +    ssidref_t ste_ssidref, ste_rssidref;
  33.228 +    struct domain *d, *rdom;
  33.229 +    domid_t rdomid;
  33.230 +    struct active_grant_entry *act;
  33.231 +    int port, i;
  33.232 +
  33.233 +    rcu_read_lock(&domlist_read_lock);
  33.234 +    read_lock(&ssid_list_rwlock);
  33.235 +
  33.236 +    /* go through all domains and adjust policy as if this domain was
  33.237 +       started now */
  33.238 +
  33.239 +    for_each_domain ( d )
  33.240 +    {
  33.241 +        struct evtchn *ports;
  33.242 +        unsigned int bucket;
  33.243 +
  33.244 +        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
  33.245 +                             (struct acm_ssid_domain *)d->ssid);
  33.246 +        ste_ssidref = ste_ssid->ste_ssidref;
  33.247 +        traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
  33.248 +                    __func__, d->domain_id, ste_ssidref);
  33.249 +        /* a) check for event channel conflicts */
  33.250 +        for ( bucket = 0; bucket < NR_EVTCHN_BUCKETS; bucket++ )
  33.251 +        {
  33.252 +            spin_lock(&d->evtchn_lock);
  33.253 +            ports = d->evtchn[bucket];
  33.254 +            if ( ports == NULL)
  33.255 +            {
  33.256 +                spin_unlock(&d->evtchn_lock);
  33.257 +                break;
  33.258 +            }
  33.259 +
  33.260 +            for ( port = 0; port < EVTCHNS_PER_BUCKET; port++ )
  33.261 +            {
  33.262 +                if ( ports[port].state == ECS_INTERDOMAIN )
  33.263 +                {
  33.264 +                    rdom = ports[port].u.interdomain.remote_dom;
  33.265 +                    rdomid = rdom->domain_id;
  33.266 +                } else {
  33.267 +                    continue; /* port unused */
  33.268 +                }
  33.269 +
  33.270 +                /* rdom now has remote domain */
  33.271 +                ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  33.272 +                                      (struct acm_ssid_domain *)(rdom->ssid));
  33.273 +                ste_rssidref = ste_rssid->ste_ssidref;
  33.274 +                traceprintk("%s: eventch: domain %x (ssidref %x) --> "
  33.275 +                            "domain %x (rssidref %x) used (port %x).\n",
  33.276 +                            __func__, d->domain_id, ste_ssidref,
  33.277 +                            rdom->domain_id, ste_rssidref, port);
  33.278 +                /* check whether on subj->ssid, obj->ssid share a common type*/
  33.279 +                if ( ! have_common_type(ste_ssidref, ste_rssidref) )
  33.280 +                {
  33.281 +                    printkd("%s: Policy violation in event channel domain "
  33.282 +                            "%x -> domain %x.\n",
  33.283 +                            __func__, d->domain_id, rdomid);
  33.284 +                    spin_unlock(&d->evtchn_lock);
  33.285 +
  33.286 +                    acm_array_append_tuple(errors,
  33.287 +                                           ACM_EVTCHN_SHARING_VIOLATION,
  33.288 +                                           d->domain_id << 16 | rdomid);
  33.289 +                    goto out;
  33.290 +                }
  33.291 +            }
  33.292 +            spin_unlock(&d->evtchn_lock);
  33.293 +        } 
  33.294 +
  33.295 +
  33.296 +        /* b) check for grant table conflicts on shared pages */
  33.297 +        spin_lock(&d->grant_table->lock);
  33.298 +        for ( i = 0; i < nr_active_grant_frames(d->grant_table); i++ )
  33.299 +        {
  33.300 +#define APP (PAGE_SIZE / sizeof(struct active_grant_entry))
  33.301 +            act = &d->grant_table->active[i/APP][i%APP];
  33.302 +            if ( act->pin != 0 ) {
  33.303 +                printkd("%s: grant dom (%hu) SHARED (%d) pin (%d)  "
  33.304 +                        "dom:(%hu) frame:(%lx)\n",
  33.305 +                        __func__, d->domain_id, i, act->pin,
  33.306 +                        act->domid, (unsigned long)act->frame);
  33.307 +                rdomid = act->domid;
  33.308 +                if ( (rdom = rcu_lock_domain_by_id(rdomid)) == NULL )
  33.309 +                {
  33.310 +                    spin_unlock(&d->grant_table->lock);
  33.311 +                    printkd("%s: domain not found ERROR!\n", __func__);
  33.312 +
  33.313 +                    acm_array_append_tuple(errors,
  33.314 +                                           ACM_DOMAIN_LOOKUP,
  33.315 +                                           rdomid);
  33.316 +                    goto out;
  33.317 +                }
  33.318 +                /* rdom now has remote domain */
  33.319 +                ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
  33.320 +                                      (struct acm_ssid_domain *)(rdom->ssid));
  33.321 +                ste_rssidref = ste_rssid->ste_ssidref;
  33.322 +                rcu_unlock_domain(rdom);
  33.323 +                if ( ! have_common_type(ste_ssidref, ste_rssidref) )
  33.324 +                {
  33.325 +                    spin_unlock(&d->grant_table->lock);
  33.326 +                    printkd("%s: Policy violation in grant table "
  33.327 +                            "sharing domain %x -> domain %x.\n",
  33.328 +                            __func__, d->domain_id, rdomid);
  33.329 +
  33.330 +                    acm_array_append_tuple(errors,
  33.331 +                                           ACM_GNTTAB_SHARING_VIOLATION,
  33.332 +                                           d->domain_id << 16 | rdomid);
  33.333 +                    goto out;
  33.334 +                }
  33.335 +            }
  33.336 +        }
  33.337 +        spin_unlock(&d->grant_table->lock);
  33.338 +    }
  33.339 +    violation = 0;
  33.340 + out:
  33.341 +    read_unlock(&ssid_list_rwlock);
  33.342 +    rcu_read_unlock(&domlist_read_lock);
  33.343 +    return violation;
  33.344 +    /*
  33.345 +       returning "violation != 0" means that existing sharing between domains
  33.346 +       would not have been allowed if the new policy had been enforced before
  33.347 +       the sharing; for ste, this means that there are at least 2 domains
  33.348 +       that have established sharing through event-channels or grant-tables
  33.349 +       but these two domains don't have no longer a common type in their
  33.350 +       typesets referenced by their ssidrefs
  33.351 +      */
  33.352 +}
  33.353 +
  33.354 +
  33.355 +/*
  33.356 + * Call ste_init_state with the current policy.
  33.357 + */
  33.358 +int
  33.359 +do_ste_init_state_curr(struct acm_sized_buffer *errors)
  33.360 +{
  33.361 +    return ste_init_state(errors);
  33.362 +}
  33.363 +
  33.364 +
  33.365 +/* set new policy; policy write-locked already */
  33.366 +static int
  33.367 +_ste_update_policy(u8 *buf, u32 buf_size, int test_only,
  33.368 +                   struct acm_sized_buffer *errors)
  33.369 +{
  33.370 +    int rc = -EFAULT;
  33.371 +    struct acm_ste_policy_buffer *ste_buf =
  33.372 +                                 (struct acm_ste_policy_buffer *)buf;
  33.373 +    void *ssidrefsbuf;
  33.374 +    struct ste_ssid *ste_ssid;
  33.375 +    struct acm_ssid_domain *rawssid;
  33.376 +    int i;
  33.377 +
  33.378 +
  33.379 +    /* 1. create and copy-in new ssidrefs buffer */
  33.380 +    ssidrefsbuf = xmalloc_array(u8,
  33.381 +                                sizeof(domaintype_t) *
  33.382 +                                 ste_buf->ste_max_types *
  33.383 +                                 ste_buf->ste_max_ssidrefs);
  33.384 +    if ( ssidrefsbuf == NULL ) {
  33.385 +        return -ENOMEM;
  33.386 +    }
  33.387 +    if ( ste_buf->ste_ssid_offset +
  33.388 +         sizeof(domaintype_t) *
  33.389 +         ste_buf->ste_max_ssidrefs *
  33.390 +         ste_buf->ste_max_types > buf_size )
  33.391 +        goto error_free;
  33.392 +
  33.393 +    arrcpy(ssidrefsbuf, 
  33.394 +           buf + ste_buf->ste_ssid_offset,
  33.395 +           sizeof(domaintype_t),
  33.396 +           ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
  33.397 +
  33.398 +
  33.399 +    /*
  33.400 +     * 3. in test mode: re-calculate sharing decisions based on running
  33.401 +     *    domains; this can fail if new policy is conflicting with sharing
  33.402 +     *    of running domains
  33.403 +     *    now: reject violating new policy; future: adjust sharing through
  33.404 +     *    revoking sharing
  33.405 +     */
  33.406 +
  33.407 +    if ( test_only ) {
  33.408 +        /* temporarily replace old policy with new one for the testing */
  33.409 +        struct ste_binary_policy orig_ste_bin_pol = ste_bin_pol;
  33.410 +        ste_bin_pol.max_types = ste_buf->ste_max_types;
  33.411 +        ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
  33.412 +        ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
  33.413 +
  33.414 +        if ( ste_init_state(errors) )
  33.415 +        {
  33.416 +            /* new policy conflicts with sharing of running domains */
  33.417 +            printk("%s: New policy conflicts with running domains. "
  33.418 +                   "Policy load aborted.\n", __func__);
  33.419 +        } else {
  33.420 +            rc = ACM_OK;
  33.421 +        }
  33.422 +        /* revert changes, no matter whether testing was successful or not */
  33.423 +        ste_bin_pol = orig_ste_bin_pol;
  33.424 +        goto error_free;
  33.425 +    }
  33.426 +
  33.427 +    /* 3. replace old policy (activate new policy) */
  33.428 +    ste_bin_pol.max_types = ste_buf->ste_max_types;
  33.429 +    ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
  33.430 +    xfree(ste_bin_pol.ssidrefs);
  33.431 +    ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
  33.432 +
  33.433 +    /* clear all ste caches */
  33.434 +    read_lock(&ssid_list_rwlock);
  33.435 +
  33.436 +    for_each_acmssid( rawssid )
  33.437 +    {
  33.438 +        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
  33.439 +        for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  33.440 +            ste_ssid->ste_cache[i].valid = ACM_STE_free;
  33.441 +    }
  33.442 +
  33.443 +    read_unlock(&ssid_list_rwlock);
  33.444 +
  33.445 +    return ACM_OK;
  33.446 +
  33.447 + error_free:
  33.448 +    if ( !test_only )
  33.449 +        printk("%s: ERROR setting policy.\n", __func__);
  33.450 +    xfree(ssidrefsbuf);
  33.451 +    return rc;
  33.452 +}
  33.453 +
  33.454 +static int
  33.455 +ste_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
  33.456 +                struct acm_sized_buffer *errors)
  33.457 +{
  33.458 +    struct acm_ste_policy_buffer *ste_buf =
  33.459 +             (struct acm_ste_policy_buffer *)buf;
  33.460 +
  33.461 +    if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
  33.462 +        return -EINVAL;
  33.463 +
  33.464 +    /* Convert endianess of policy */
  33.465 +    ste_buf->policy_code = be32_to_cpu(ste_buf->policy_code);
  33.466 +    ste_buf->policy_version = be32_to_cpu(ste_buf->policy_version);
  33.467 +    ste_buf->ste_max_types = be32_to_cpu(ste_buf->ste_max_types);
  33.468 +    ste_buf->ste_max_ssidrefs = be32_to_cpu(ste_buf->ste_max_ssidrefs);
  33.469 +    ste_buf->ste_ssid_offset = be32_to_cpu(ste_buf->ste_ssid_offset);
  33.470 +
  33.471 +    /* policy type and version checks */
  33.472 +    if ( (ste_buf->policy_code != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ||
  33.473 +         (ste_buf->policy_version != ACM_STE_VERSION) )
  33.474 +        return -EINVAL;
  33.475 +
  33.476 +    /* during boot dom0_chwall_ssidref is set */
  33.477 +    if ( is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs) )
  33.478 +        return -EINVAL;
  33.479 +
  33.480 +    return _ste_update_policy(buf, buf_size, 1, errors);
  33.481 +}
  33.482 +
  33.483 +static int
  33.484 +ste_set_policy(u8 *buf, u32 buf_size)
  33.485 +{
  33.486 +    return _ste_update_policy(buf, buf_size, 0, NULL);
  33.487 +}
  33.488 +
  33.489 +static int 
  33.490 +ste_dump_stats(u8 *buf, u16 buf_len)
  33.491 +{
  33.492 +    struct acm_ste_stats_buffer stats;
  33.493 +
  33.494 +    /* now send the hook counts to user space */
  33.495 +    stats.ec_eval_count =
  33.496 +                    cpu_to_be32(atomic_read(&ste_bin_pol.ec_eval_count));
  33.497 +    stats.gt_eval_count =
  33.498 +                    cpu_to_be32(atomic_read(&ste_bin_pol.gt_eval_count));
  33.499 +    stats.ec_denied_count =
  33.500 +                    cpu_to_be32(atomic_read(&ste_bin_pol.ec_denied_count));
  33.501 +    stats.gt_denied_count =
  33.502 +                    cpu_to_be32(atomic_read(&ste_bin_pol.gt_denied_count));
  33.503 +    stats.ec_cachehit_count =
  33.504 +                    cpu_to_be32(atomic_read(&ste_bin_pol.ec_cachehit_count));
  33.505 +    stats.gt_cachehit_count =
  33.506 +                    cpu_to_be32(atomic_read(&ste_bin_pol.gt_cachehit_count));
  33.507 +
  33.508 +    if ( buf_len < sizeof(struct acm_ste_stats_buffer) )
  33.509 +        return -ENOMEM;
  33.510 +
  33.511 +    memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
  33.512 +
  33.513 +    return sizeof(struct acm_ste_stats_buffer);
  33.514 +}
  33.515 +
  33.516 +static int
  33.517 +ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
  33.518 +{
  33.519 +    int i;
  33.520 +
  33.521 +    /* fill in buffer */
  33.522 +    if ( ste_bin_pol.max_types > len )
  33.523 +        return -EFAULT;
  33.524 +
  33.525 +    if ( ssidref >= ste_bin_pol.max_ssidrefs )
  33.526 +        return -EFAULT;
  33.527 +
  33.528 +    /* read types for chwall ssidref */
  33.529 +    for( i = 0; i< ste_bin_pol.max_types; i++ )
  33.530 +    {
  33.531 +        if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
  33.532 +            buf[i] = 1;
  33.533 +        else
  33.534 +            buf[i] = 0;
  33.535 +    }
  33.536 +    return ste_bin_pol.max_types;
  33.537 +}
  33.538 +
  33.539 +/* we need to go through this before calling the hooks,
  33.540 + * returns 1 == cache hit */
  33.541 +static int inline
  33.542 +check_cache(struct domain *dom, domid_t rdom)
  33.543 +{
  33.544 +    struct ste_ssid *ste_ssid;
  33.545 +    int i;
  33.546 +
  33.547 +    printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
  33.548 +
  33.549 +    if (dom->ssid == NULL)
  33.550 +        return 0;
  33.551 +    ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
  33.552 +                         (struct acm_ssid_domain *)(dom->ssid));
  33.553 +
  33.554 +    for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  33.555 +    {
  33.556 +        if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
  33.557 +             (ste_ssid->ste_cache[i].id == rdom) )
  33.558 +        {
  33.559 +            printkd("cache hit (entry %x, id= %x!\n",
  33.560 +                    i,
  33.561 +                    ste_ssid->ste_cache[i].id);
  33.562 +            return 1;
  33.563 +        }
  33.564 +    }
  33.565 +    return 0;
  33.566 +}
  33.567 +
  33.568 +
  33.569 +/* we only get here if there is NO entry yet; no duplication check! */
  33.570 +static void inline
  33.571 +cache_result(struct domain *subj, struct domain *obj) {
  33.572 +    struct ste_ssid *ste_ssid;
  33.573 +    int i;
  33.574 +
  33.575 +    printkd("caching from doms: %x --> %x.\n",
  33.576 +            subj->domain_id, obj->domain_id);
  33.577 +
  33.578 +    if ( subj->ssid == NULL )
  33.579 +        return;
  33.580 +
  33.581 +    ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
  33.582 +                         (struct acm_ssid_domain *)(subj)->ssid);
  33.583 +
  33.584 +    for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  33.585 +        if ( ste_ssid->ste_cache[i].valid == ACM_STE_free )
  33.586 +            break;
  33.587 +    if ( i < ACM_TE_CACHE_SIZE )
  33.588 +    {
  33.589 +        ste_ssid->ste_cache[i].valid = ACM_STE_valid;
  33.590 +        ste_ssid->ste_cache[i].id = obj->domain_id;
  33.591 +    } else
  33.592 +        printk ("Cache of dom %x is full!\n", subj->domain_id);
  33.593 +}
  33.594 +
  33.595 +/* deletes entries for domain 'id' from all caches (re-use) */
  33.596 +static void inline
  33.597 +clean_id_from_cache(domid_t id) 
  33.598 +{
  33.599 +    struct ste_ssid *ste_ssid;
  33.600 +    int i;
  33.601 +    struct acm_ssid_domain *rawssid;
  33.602 +
  33.603 +    printkd("deleting cache for dom %x.\n", id);
  33.604 +
  33.605 +    read_lock(&ssid_list_rwlock);
  33.606 +    /* look through caches of all domains */
  33.607 +
  33.608 +    for_each_acmssid ( rawssid )
  33.609 +    {
  33.610 +        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
  33.611 +
  33.612 +        if ( !ste_ssid )
  33.613 +        {
  33.614 +            printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n",
  33.615 +                   __func__);
  33.616 +            goto out;
  33.617 +        }
  33.618 +        for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
  33.619 +            if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
  33.620 +                 (ste_ssid->ste_cache[i].id == id) )
  33.621 +                ste_ssid->ste_cache[i].valid = ACM_STE_free;
  33.622 +    }
  33.623 +
  33.624 + out:
  33.625 +    read_unlock(&ssid_list_rwlock);
  33.626 +}
  33.627 +
  33.628 +/***************************
  33.629 + * Authorization functions
  33.630 + **************************/
  33.631 +static int 
  33.632 +ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
  33.633 +{      
  33.634 +    /* check for ssidref in range for policy */
  33.635 +    ssidref_t ste_ssidref;
  33.636 +
  33.637 +    traceprintk("%s.\n", __func__);
  33.638 +
  33.639 +    read_lock(&acm_bin_pol_rwlock);
  33.640 +
  33.641 +    ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
  33.642 +
  33.643 +    if ( ste_ssidref >= ste_bin_pol.max_ssidrefs )
  33.644 +    {
  33.645 +        printk("%s: ERROR ste_ssidref > max(%x).\n", 
  33.646 +               __func__, ste_bin_pol.max_ssidrefs-1);
  33.647 +        read_unlock(&acm_bin_pol_rwlock);
  33.648 +        return ACM_ACCESS_DENIED;
  33.649 +    }
  33.650 +
  33.651 +    read_unlock(&acm_bin_pol_rwlock);
  33.652 +
  33.653 +    return ACM_ACCESS_PERMITTED;
  33.654 +}
  33.655 +
  33.656 +static int
  33.657 +ste_domain_create(void *subject_ssid, ssidref_t ssidref, domid_t  domid)
  33.658 +{
  33.659 +    return ste_pre_domain_create(subject_ssid, ssidref);
  33.660 +}
  33.661 +
  33.662 +
  33.663 +static void 
  33.664 +ste_domain_destroy(void *subject_ssid, struct domain *d)
  33.665 +{
  33.666 +    /* clean all cache entries for destroyed domain (might be re-used) */
  33.667 +    clean_id_from_cache(d->domain_id);
  33.668 +}
  33.669 +
  33.670 +/* -------- EVENTCHANNEL OPERATIONS -----------*/
  33.671 +static int
  33.672 +ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) {
  33.673 +    struct domain *subj, *obj;
  33.674 +    int ret;
  33.675 +    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  33.676 +                (id1 == DOMID_SELF) ? current->domain->domain_id : id1,
  33.677 +                (id2 == DOMID_SELF) ? current->domain->domain_id : id2);
  33.678 +
  33.679 +    if ( id1 == DOMID_SELF )
  33.680 +        id1 = current->domain->domain_id;
  33.681 +    if ( id2 == DOMID_SELF )
  33.682 +        id2 = current->domain->domain_id;
  33.683 +
  33.684 +    subj = rcu_lock_domain_by_id(id1);
  33.685 +    obj  = rcu_lock_domain_by_id(id2);
  33.686 +    if ( (subj == NULL) || (obj == NULL) )
  33.687 +    {
  33.688 +        ret = ACM_ACCESS_DENIED;
  33.689 +        goto out;
  33.690 +    }
  33.691 +    /* cache check late */
  33.692 +    if ( check_cache(subj, obj->domain_id) )
  33.693 +    {
  33.694 +        atomic_inc(&ste_bin_pol.ec_cachehit_count);
  33.695 +        ret = ACM_ACCESS_PERMITTED;
  33.696 +        goto out;
  33.697 +    }
  33.698 +    atomic_inc(&ste_bin_pol.ec_eval_count);
  33.699 +
  33.700 +    if ( share_common_type(subj, obj) )
  33.701 +    {
  33.702 +        cache_result(subj, obj);
  33.703 +        ret = ACM_ACCESS_PERMITTED;
  33.704 +    }
  33.705 +    else
  33.706 +    {
  33.707 +        atomic_inc(&ste_bin_pol.ec_denied_count);
  33.708 +        ret = ACM_ACCESS_DENIED;
  33.709 +    }
  33.710 +
  33.711 +  out:
  33.712 +    if ( obj != NULL )
  33.713 +        rcu_unlock_domain(obj);
  33.714 +    if ( subj != NULL )
  33.715 +        rcu_unlock_domain(subj);
  33.716 +    return ret;
  33.717 +}
  33.718 +
  33.719 +static int
  33.720 +ste_pre_eventchannel_interdomain(domid_t id)
  33.721 +{
  33.722 +    struct domain *subj=NULL, *obj=NULL;
  33.723 +    int ret;
  33.724 +
  33.725 +    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  33.726 +                current->domain->domain_id,
  33.727 +                (id == DOMID_SELF) ? current->domain->domain_id : id);
  33.728 +
  33.729 +    /* following is a bit longer but ensures that we
  33.730 +     * "put" only domains that we where "find"-ing 
  33.731 +     */
  33.732 +    if ( id == DOMID_SELF )
  33.733 +        id = current->domain->domain_id;
  33.734 +
  33.735 +    subj = current->domain;
  33.736 +    obj  = rcu_lock_domain_by_id(id);
  33.737 +    if ( obj == NULL )
  33.738 +    {
  33.739 +        ret = ACM_ACCESS_DENIED;
  33.740 +        goto out;
  33.741 +    }
  33.742 +
  33.743 +    /* cache check late, but evtchn is not on performance critical path */
  33.744 +    if ( check_cache(subj, obj->domain_id) )
  33.745 +    {
  33.746 +        atomic_inc(&ste_bin_pol.ec_cachehit_count);
  33.747 +        ret = ACM_ACCESS_PERMITTED;
  33.748 +        goto out;
  33.749 +    }
  33.750 +
  33.751 +    atomic_inc(&ste_bin_pol.ec_eval_count);
  33.752 +
  33.753 +    if ( share_common_type(subj, obj) )
  33.754 +    {
  33.755 +        cache_result(subj, obj);
  33.756 +        ret = ACM_ACCESS_PERMITTED;
  33.757 +    }
  33.758 +    else
  33.759 +    {
  33.760 +        atomic_inc(&ste_bin_pol.ec_denied_count);
  33.761 +        ret = ACM_ACCESS_DENIED;
  33.762 +    }
  33.763 +
  33.764 + out:
  33.765 +    if ( obj != NULL )
  33.766 +        rcu_unlock_domain(obj);
  33.767 +    return ret;
  33.768 +}
  33.769 +
  33.770 +/* -------- SHARED MEMORY OPERATIONS -----------*/
  33.771 +
  33.772 +static int
  33.773 +ste_pre_grant_map_ref (domid_t id)
  33.774 +{
  33.775 +    struct domain *obj, *subj;
  33.776 +    int ret;
  33.777 +    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  33.778 +                current->domain->domain_id, id);
  33.779 +
  33.780 +    if ( check_cache(current->domain, id) )
  33.781 +    {
  33.782 +        atomic_inc(&ste_bin_pol.gt_cachehit_count);
  33.783 +        return ACM_ACCESS_PERMITTED;
  33.784 +    }
  33.785 +    atomic_inc(&ste_bin_pol.gt_eval_count);
  33.786 +    subj = current->domain;
  33.787 +    obj = rcu_lock_domain_by_id(id);
  33.788 +
  33.789 +    if ( share_common_type(subj, obj) )
  33.790 +    {
  33.791 +        cache_result(subj, obj);
  33.792 +        ret = ACM_ACCESS_PERMITTED;
  33.793 +    }
  33.794 +    else
  33.795 +    {
  33.796 +        atomic_inc(&ste_bin_pol.gt_denied_count);
  33.797 +        printkd("%s: ACCESS DENIED!\n", __func__);
  33.798 +        ret = ACM_ACCESS_DENIED;
  33.799 +    }
  33.800 +    if ( obj != NULL )
  33.801 +        rcu_unlock_domain(obj);
  33.802 +    return ret;
  33.803 +}
  33.804 +
  33.805 +
  33.806 +/* since setting up grant tables involves some implicit information
  33.807 +   flow from the creating domain to the domain that is setup, we 
  33.808 +   check types in addition to the general authorization */
  33.809 +static int
  33.810 +ste_pre_grant_setup (domid_t id)
  33.811 +{
  33.812 +    struct domain *obj, *subj;
  33.813 +    int ret;
  33.814 +    traceprintk("%s: dom%x-->dom%x.\n", __func__,
  33.815 +                current->domain->domain_id, id);
  33.816 +
  33.817 +    if ( check_cache(current->domain, id) )
  33.818 +    {
  33.819 +        atomic_inc(&ste_bin_pol.gt_cachehit_count);
  33.820 +        return ACM_ACCESS_PERMITTED;
  33.821 +    }
  33.822 +    atomic_inc(&ste_bin_pol.gt_eval_count);
  33.823 +    /* a) check authorization (eventually use specific capabilities) */
  33.824 +    if ( !IS_PRIV(current->domain) )
  33.825 +    {
  33.826 +        printk("%s: Grant table management authorization denied ERROR!\n",
  33.827 +               __func__);
  33.828 +        return ACM_ACCESS_DENIED;
  33.829 +    }
  33.830 +    /* b) check types */
  33.831 +    subj = current->domain;
  33.832 +    obj = rcu_lock_domain_by_id(id);
  33.833 +
  33.834 +    if ( share_common_type(subj, obj) )
  33.835 +    {
  33.836 +        cache_result(subj, obj);
  33.837 +        ret = ACM_ACCESS_PERMITTED;
  33.838 +    }
  33.839 +    else
  33.840 +    {
  33.841 +        atomic_inc(&ste_bin_pol.gt_denied_count);
  33.842 +        ret = ACM_ACCESS_DENIED;
  33.843 +    }
  33.844 +    if ( obj != NULL )
  33.845 +        rcu_unlock_domain(obj);
  33.846 +    return ret;
  33.847 +}
  33.848 +
  33.849 +/* -------- DOMAIN-Requested Decision hooks -----------*/
  33.850 +
  33.851 +static int
  33.852 +ste_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
  33.853 +{
  33.854 +    int hct = have_common_type(
  33.855 +        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
  33.856 +        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
  33.857 +    return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
  33.858 +}
  33.859 +
  33.860 +static int
  33.861 +ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
  33.862 +{
  33.863 +    int iss = is_superset(
  33.864 +        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
  33.865 +        GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
  33.866 +    return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
  33.867 +}
  33.868 +
  33.869 +static int
  33.870 +ste_is_default_policy(void)
  33.871 +{
  33.872 +    return ((ste_bin_pol.max_types    == 1) &&
  33.873 +            (ste_bin_pol.max_ssidrefs == 2));
  33.874 +}
  33.875 +
  33.876 +/* now define the hook structure similarly to LSM */
  33.877 +struct acm_operations acm_simple_type_enforcement_ops = {
  33.878 +
  33.879 +    /* policy management services */
  33.880 +    .init_domain_ssid       = ste_init_domain_ssid,
  33.881 +    .free_domain_ssid       = ste_free_domain_ssid,
  33.882 +    .dump_binary_policy     = ste_dump_policy,
  33.883 +    .test_binary_policy     = ste_test_policy,
  33.884 +    .set_binary_policy      = ste_set_policy,
  33.885 +    .dump_statistics        = ste_dump_stats,
  33.886 +    .dump_ssid_types        = ste_dump_ssid_types,
  33.887 +
  33.888 +    /* domain management control hooks */
  33.889 +    .domain_create          = ste_domain_create,
  33.890 +    .domain_destroy         = ste_domain_destroy,
  33.891 +
  33.892 +    /* event channel control hooks */
  33.893 +    .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
  33.894 +    .fail_eventchannel_unbound = NULL,
  33.895 +    .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
  33.896 +    .fail_eventchannel_interdomain = NULL,
  33.897 +
  33.898 +    /* grant table control hooks */
  33.899 +    .pre_grant_map_ref      = ste_pre_grant_map_ref,
  33.900 +    .fail_grant_map_ref     = NULL,
  33.901 +    .pre_grant_setup        = ste_pre_grant_setup,
  33.902 +    .fail_grant_setup       = NULL,
  33.903 +    .sharing                = ste_sharing,
  33.904 +    .authorization          = ste_authorization,
  33.905 +
  33.906 +    .is_default_policy      = ste_is_default_policy,
  33.907 +};
  33.908 +
  33.909 +/*
  33.910 + * Local variables:
  33.911 + * mode: C
  33.912 + * c-set-style: "BSD"
  33.913 + * c-basic-offset: 4
  33.914 + * tab-width: 4
  33.915 + * indent-tabs-mode: nil
  33.916 + * End:
  33.917 + */
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/xen/xsm/acm/acm_xsm_hooks.c	Fri Aug 31 11:41:49 2007 +0100
    34.3 @@ -0,0 +1,72 @@
    34.4 +/****************************************************************
    34.5 + * acm_xsm_hooks.c
    34.6 + * 
    34.7 + * Copyright (C) 2005 IBM Corporation
    34.8 + *
    34.9 + * Author:
   34.10 + * Reiner Sailer <sailer@watson.ibm.com>
   34.11 + *
   34.12 + * Contributors: 
   34.13 + * Michael LeMay, <mdlemay@epoch.ncsc.mil>
   34.14 + * George Coker, <gscoker@alpha.ncsc.mil>
   34.15 + *
   34.16 + * sHype hooks for XSM based on the original ACM hooks.
   34.17 + *
   34.18 + * This program is free software; you can redistribute it and/or
   34.19 + * modify it under the terms of the GNU General Public License as
   34.20 + * published by the Free Software Foundation, version 2 of the
   34.21 + * License.
   34.22 + *
   34.23 + */
   34.24 +
   34.25 +#include <xsm/xsm.h>
   34.26 +#include <acm/acm_hooks.h>
   34.27 +#include <public/acm.h>
   34.28 +
   34.29 +static int acm_grant_mapref (struct domain *ld, struct domain *rd,
   34.30 +                                                                 uint32_t flags) 
   34.31 +{
   34.32 +    domid_t id = rd->domain_id;
   34.33 +
   34.34 +    return acm_pre_grant_map_ref(id);
   34.35 +}
   34.36 +
   34.37 +static int acm_evtchn_unbound (struct domain *d1, struct evtchn *chn1, domid_t id2) 
   34.38 +{
   34.39 +    domid_t id1 = d1->domain_id;
   34.40 +    
   34.41 +    return acm_pre_eventchannel_unbound(id1, id2);
   34.42 +}
   34.43 +
   34.44 +static int acm_evtchn_interdomain (struct domain *d1, struct evtchn *chn1, 
   34.45 +                                        struct domain *d2, struct evtchn *chn2) 
   34.46 +{
   34.47 +    domid_t id2 = d2->domain_id;
   34.48 +
   34.49 +    return acm_pre_eventchannel_interdomain(id2);
   34.50 +}
   34.51 +
   34.52 +static void acm_security_domaininfo (struct domain *d, 
   34.53 +                                        struct xen_domctl_getdomaininfo *info)
   34.54 +{
   34.55 +    if ( d->ssid != NULL )
   34.56 +        info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
   34.57 +    else    
   34.58 +        info->ssidref = ACM_DEFAULT_SSID;
   34.59 +}
   34.60 +
   34.61 +extern long do_acm_op(XEN_GUEST_HANDLE(xsm_op_t) arg);
   34.62 +
   34.63 +struct xsm_operations acm_xsm_ops = {
   34.64 +    .domain_create = acm_domain_create,
   34.65 +    .free_security_domain = acm_domain_destroy,
   34.66 +
   34.67 +    .grant_mapref = acm_grant_mapref,
   34.68 +
   34.69 +    .evtchn_unbound = acm_evtchn_unbound,
   34.70 +    .evtchn_interdomain = acm_evtchn_interdomain,
   34.71 +
   34.72 +    .security_domaininfo = acm_security_domaininfo,
   34.73 +
   34.74 +    .__do_xsm_op = do_acm_op,
   34.75 +};