aboutsummaryrefslogtreecommitdiffstats
path: root/xen/xsm
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2011-03-25 21:47:57 +0000
committerKeir Fraser <keir@xen.org>2011-03-25 21:47:57 +0000
commit6102cace934c5ef156e7e1e21966cf3950dc40e5 (patch)
tree612c892c08a8a6c371b3c02981b2699e7ebdc9ae /xen/xsm
parent662f524483de23084ae4dde930fa7570fb15e033 (diff)
downloadxen-6102cace934c5ef156e7e1e21966cf3950dc40e5.tar.gz
xen-6102cace934c5ef156e7e1e21966cf3950dc40e5.tar.bz2
xen-6102cace934c5ef156e7e1e21966cf3950dc40e5.zip
Remove unmaintained Access Control Module (ACM) from hypervisor.
Signed-off-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/xsm')
-rw-r--r--xen/xsm/Makefile1
-rw-r--r--xen/xsm/acm/Makefile7
-rw-r--r--xen/xsm/acm/acm_chinesewall_hooks.c721
-rw-r--r--xen/xsm/acm/acm_core.c406
-rw-r--r--xen/xsm/acm/acm_null_hooks.c95
-rw-r--r--xen/xsm/acm/acm_ops.c212
-rw-r--r--xen/xsm/acm/acm_policy.c893
-rw-r--r--xen/xsm/acm/acm_simple_type_enforcement_hooks.c924
-rw-r--r--xen/xsm/acm/acm_xsm_hooks.c74
-rw-r--r--xen/xsm/xsm_policy.c1
10 files changed, 0 insertions, 3334 deletions
diff --git a/xen/xsm/Makefile b/xen/xsm/Makefile
index 02f55d8e1a..16c13b507f 100644
--- a/xen/xsm/Makefile
+++ b/xen/xsm/Makefile
@@ -5,4 +5,3 @@ obj-y += dummy.o
endif
subdir-$(FLASK_ENABLE) += flask
-subdir-$(ACM_SECURITY) += acm
diff --git a/xen/xsm/acm/Makefile b/xen/xsm/acm/Makefile
deleted file mode 100644
index b3ddbc13c8..0000000000
--- a/xen/xsm/acm/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-y += acm_core.o
-obj-y += acm_policy.o
-obj-y += acm_simple_type_enforcement_hooks.o
-obj-y += acm_chinesewall_hooks.o
-obj-y += acm_null_hooks.o
-obj-y += acm_xsm_hooks.o
-obj-y += acm_ops.o
diff --git a/xen/xsm/acm/acm_chinesewall_hooks.c b/xen/xsm/acm/acm_chinesewall_hooks.c
deleted file mode 100644
index 977c45ff2a..0000000000
--- a/xen/xsm/acm/acm_chinesewall_hooks.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/****************************************************************
- * acm_chinesewall_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributions:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype Chinese Wall Policy for Xen
- * This code implements the hooks that are called
- * throughout Xen operations and decides authorization
- * based on domain types and Chinese Wall conflict type
- * sets. The CHWALL policy decides if a new domain can be started
- * based on the types of running domains and the type of the
- * new domain to be started. If the new domain's type is in
- * conflict with types of running domains, then this new domain
- * is not allowed to be created. A domain can have multiple types,
- * in which case all types of a new domain must be conflict-free
- * with all types of already running domains.
- *
- * indent -i4 -kr -nut
- *
- */
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <public/xsm/acm.h>
-#include <asm/atomic.h>
-#include <xsm/acm/acm_core.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-
-ssidref_t dom0_chwall_ssidref = 0x0001;
-
-/* local cache structures for chinese wall policy */
-struct chwall_binary_policy chwall_bin_pol;
-
-/*
- * Initializing chinese wall policy (will be filled by policy partition
- * using setpolicy command)
- */
-int acm_init_chwall_policy(void)
-{
- /* minimal startup policy; policy write-locked already */
- chwall_bin_pol.max_types = 1;
- chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref;
- chwall_bin_pol.max_conflictsets = 1;
- chwall_bin_pol.ssidrefs =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_ssidrefs *
- chwall_bin_pol.max_types);
- chwall_bin_pol.conflict_sets =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_conflictsets *
- chwall_bin_pol.max_types);
- chwall_bin_pol.running_types =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_types);
- chwall_bin_pol.conflict_aggregate_set =
- (domaintype_t *) xmalloc_array(domaintype_t,
- chwall_bin_pol.max_types);
-
- if ( (chwall_bin_pol.conflict_sets == NULL)
- || (chwall_bin_pol.running_types == NULL)
- || (chwall_bin_pol.ssidrefs == NULL)
- || (chwall_bin_pol.conflict_aggregate_set == NULL) )
- return ACM_INIT_SSID_ERROR;
-
- /* initialize state */
- memset((void *) chwall_bin_pol.ssidrefs, 0,
- chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types *
- sizeof(domaintype_t));
- memset((void *) chwall_bin_pol.conflict_sets, 0,
- chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types *
- sizeof(domaintype_t));
- memset((void *) chwall_bin_pol.running_types, 0,
- chwall_bin_pol.max_types * sizeof(domaintype_t));
- memset((void *) chwall_bin_pol.conflict_aggregate_set, 0,
- chwall_bin_pol.max_types * sizeof(domaintype_t));
- return ACM_OK;
-}
-
-
-static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
-{
- struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
- traceprintk("%s.\n", __func__);
-
- if ( chwall_ssidp == NULL )
- return ACM_INIT_SSID_ERROR;
-
- chwall_ssidp->chwall_ssidref =
- GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
-
- if ( chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
- {
- printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset "
- "(0).\n",
- __func__, chwall_ssidp->chwall_ssidref);
- xfree(chwall_ssidp);
- return ACM_INIT_SSID_ERROR;
- }
- (*chwall_ssid) = chwall_ssidp;
- printkd("%s: determined chwall_ssidref to %x.\n",
- __func__, chwall_ssidp->chwall_ssidref);
- return ACM_OK;
-}
-
-
-static void chwall_free_domain_ssid(void *chwall_ssid)
-{
- xfree(chwall_ssid);
- return;
-}
-
-
-/* dump chinese wall cache; policy read-locked already */
-static int chwall_dump_policy(u8 * buf, u32 buf_size)
-{
- struct acm_chwall_policy_buffer *chwall_buf =
- (struct acm_chwall_policy_buffer *) buf;
- int ret = 0;
-
- if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
- return -EINVAL;
-
- chwall_buf->chwall_max_types = cpu_to_be32(chwall_bin_pol.max_types);
- chwall_buf->chwall_max_ssidrefs = cpu_to_be32(chwall_bin_pol.max_ssidrefs);
- chwall_buf->policy_code = cpu_to_be32(ACM_CHINESE_WALL_POLICY);
- chwall_buf->chwall_ssid_offset =
- cpu_to_be32(sizeof(struct acm_chwall_policy_buffer));
- chwall_buf->chwall_max_conflictsets =
- cpu_to_be32(chwall_bin_pol.max_conflictsets);
- chwall_buf->chwall_conflict_sets_offset =
- cpu_to_be32(be32_to_cpu(chwall_buf->chwall_ssid_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
- chwall_bin_pol.max_types);
- chwall_buf->chwall_running_types_offset =
- cpu_to_be32(be32_to_cpu(chwall_buf->chwall_conflict_sets_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
- chwall_bin_pol.max_types);
- chwall_buf->chwall_conflict_aggregate_offset =
- cpu_to_be32(be32_to_cpu(chwall_buf->chwall_running_types_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_types);
-
- ret = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset) +
- sizeof(domaintype_t) * chwall_bin_pol.max_types;
-
- ret = (ret + 7) & ~7;
-
- if ( buf_size < ret )
- return -EINVAL;
-
- /* now copy buffers over */
- arrcpy16((u16 *) (buf + be32_to_cpu(chwall_buf->chwall_ssid_offset)),
- chwall_bin_pol.ssidrefs,
- chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
-
- arrcpy16((u16 *) (buf +
- be32_to_cpu(chwall_buf->chwall_conflict_sets_offset)),
- chwall_bin_pol.conflict_sets,
- chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
-
- arrcpy16((u16 *) (buf +
- be32_to_cpu(chwall_buf->chwall_running_types_offset)),
- chwall_bin_pol.running_types, chwall_bin_pol.max_types);
-
- arrcpy16((u16 *) (buf +
- be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset)),
- chwall_bin_pol.conflict_aggregate_set,
- chwall_bin_pol.max_types);
- return ret;
-}
-
-/*
- * Adapt security state (running_types and conflict_aggregate_set) to all
- * running domains; chwall_init_state is called when a policy is changed
- * to bring the security information into a consistent state and to detect
- * violations (return != 0) from a security point of view, we simulate
- * that all running domains are re-started
- */
-static int
-chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
- domaintype_t * ssidrefs,
- domaintype_t * conflict_sets,
- domaintype_t * running_types,
- domaintype_t * conflict_aggregate_set,
- struct acm_sized_buffer *errors /* may be NULL */)
-{
- int violation = 0, i, j;
- struct chwall_ssid *chwall_ssid;
- ssidref_t chwall_ssidref;
- struct acm_ssid_domain *rawssid;
-
- read_lock(&ssid_list_rwlock);
-
- /* go through all domains and adjust policy as if this domain was
- * started now
- */
- for_each_acmssid( rawssid )
- {
- chwall_ssid =
- GET_SSIDP(ACM_CHINESE_WALL_POLICY, rawssid);
- chwall_ssidref = chwall_ssid->chwall_ssidref;
- traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
- __func__, d->domain_id, chwall_ssidref);
- /* a) adjust types ref-count for running domains */
- for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
- running_types[i] +=
- ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
-
- /* b) check for conflict */
- for ( i = 0; i < chwall_buf->chwall_max_types; i++ )
- if ( conflict_aggregate_set[i] &&
- ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i] )
- {
- printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
- __func__, i);
- violation = 1;
-
- acm_array_append_tuple(errors, ACM_CHWALL_CONFLICT, i);
-
- goto out;
- }
-
- /* set violation and break out of the loop */
- /* c) adapt conflict aggregate set for this domain
- * (notice conflicts)
- */
- for ( i = 0; i < chwall_buf->chwall_max_conflictsets; i++ )
- {
- int common = 0;
- /* check if conflict_set_i and ssidref have common types */
- for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
- if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
- ssidrefs[chwall_ssidref *
- chwall_buf->chwall_max_types + j] )
- {
- common = 1;
- break;
- }
-
- if ( common == 0 )
- continue; /* try next conflict set */
-
- /* now add types of the conflict set to conflict_aggregate_set
- * (except types in chwall_ssidref)
- */
- for ( j = 0; j < chwall_buf->chwall_max_types; j++ )
- if ( conflict_sets[i * chwall_buf->chwall_max_types + j] &&
- !ssidrefs[chwall_ssidref *
- chwall_buf->chwall_max_types + j] )
- conflict_aggregate_set[j]++;
- }
- }
- out:
- read_unlock(&ssid_list_rwlock);
- return violation;
- /* returning "violation != 0" means that the currently running set of
- * domains would not be possible if the new policy had been enforced
- * before starting them; for chinese wall, this means that the new
- * policy includes at least one conflict set of which more than one
- * type is currently running
- */
-}
-
-
-int
-do_chwall_init_state_curr(struct acm_sized_buffer *errors)
-{
- struct acm_chwall_policy_buffer chwall_buf =
- {
- /* only these two are important */
- .chwall_max_types = chwall_bin_pol.max_types,
- .chwall_max_conflictsets = chwall_bin_pol.max_conflictsets,
- };
- /* reset running_types and aggregate set for recalculation */
- memset(chwall_bin_pol.running_types,
- 0x0,
- sizeof(domaintype_t) * chwall_bin_pol.max_types);
- memset(chwall_bin_pol.conflict_aggregate_set,
- 0x0,
- sizeof(domaintype_t) * chwall_bin_pol.max_types);
- return chwall_init_state(&chwall_buf,
- chwall_bin_pol.ssidrefs,
- chwall_bin_pol.conflict_sets,
- chwall_bin_pol.running_types,
- chwall_bin_pol.conflict_aggregate_set,
- errors);
-}
-
-/*
- * Attempt to set the policy. This function must be called in test_only
- * mode first to only perform checks. A second call then does the
- * actual changes.
- */
-static int _chwall_update_policy(u8 *buf, u32 buf_size, int test_only,
- struct acm_sized_buffer *errors)
-{
- int rc = -EFAULT;
- /* policy write-locked already */
- struct acm_chwall_policy_buffer *chwall_buf =
- (struct acm_chwall_policy_buffer *) buf;
- void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL,
- *conflict_aggregate_set = NULL;
-
- /* 1. allocate new buffers */
- ssids =
- xmalloc_array(domaintype_t,
- chwall_buf->chwall_max_types *
- chwall_buf->chwall_max_ssidrefs);
- conflict_sets =
- xmalloc_array(domaintype_t,
- chwall_buf->chwall_max_conflictsets *
- chwall_buf->chwall_max_types);
- running_types =
- xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
- conflict_aggregate_set =
- xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
-
- if ( (ssids == NULL) || (conflict_sets == NULL) ||
- (running_types == NULL) || (conflict_aggregate_set == NULL) )
- goto error_free;
-
- /* 2. set new policy */
- if ( chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
- chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
- buf_size )
- goto error_free;
-
- arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
- sizeof(domaintype_t),
- chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
-
- if ( chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
- chwall_buf->chwall_max_types *
- chwall_buf->chwall_max_conflictsets > buf_size )
- goto error_free;
-
- arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
- sizeof(domaintype_t),
- chwall_buf->chwall_max_types *
- chwall_buf->chwall_max_conflictsets);
-
- /* we also use new state buffers since max_types can change */
- memset(running_types, 0,
- sizeof(domaintype_t) * chwall_buf->chwall_max_types);
- memset(conflict_aggregate_set, 0,
- sizeof(domaintype_t) * chwall_buf->chwall_max_types);
-
- /* 3. now re-calculate the state for the new policy based on
- * running domains; this can fail if new policy is conflicting
- * with running domains
- */
- if ( chwall_init_state(chwall_buf, ssids,
- conflict_sets, running_types,
- conflict_aggregate_set,
- errors))
- {
- printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
- __func__);
- goto error_free; /* new policy conflicts with running domains */
- }
-
- /* if this was only a test run, exit with ACM_OK */
- if ( test_only )
- {
- rc = ACM_OK;
- goto error_free;
- }
-
- /* 4. free old policy buffers, replace with new ones */
- chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
- chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
- chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
- xfree(chwall_bin_pol.ssidrefs);
- xfree(chwall_bin_pol.conflict_aggregate_set);
- xfree(chwall_bin_pol.running_types);
- xfree(chwall_bin_pol.conflict_sets);
- chwall_bin_pol.ssidrefs = ssids;
- chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
- chwall_bin_pol.running_types = running_types;
- chwall_bin_pol.conflict_sets = conflict_sets;
-
- return ACM_OK;
-
- error_free:
- if ( !test_only )
- printk("%s: ERROR setting policy.\n", __func__);
-
- xfree(ssids);
- xfree(conflict_sets);
- xfree(running_types);
- xfree(conflict_aggregate_set);
- return rc;
-}
-
-/*
- * This function MUST be called before the chwall_ste_policy function!
- */
-static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *errors)
-{
- struct acm_chwall_policy_buffer *chwall_buf =
- (struct acm_chwall_policy_buffer *) buf;
-
- if ( buf_size < sizeof(struct acm_chwall_policy_buffer) )
- return -EINVAL;
-
- /* rewrite the policy due to endianess */
- chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code);
- chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version);
- chwall_buf->chwall_max_types =
- be32_to_cpu(chwall_buf->chwall_max_types);
- chwall_buf->chwall_max_ssidrefs =
- be32_to_cpu(chwall_buf->chwall_max_ssidrefs);
- chwall_buf->chwall_max_conflictsets =
- be32_to_cpu(chwall_buf->chwall_max_conflictsets);
- chwall_buf->chwall_ssid_offset =
- be32_to_cpu(chwall_buf->chwall_ssid_offset);
- chwall_buf->chwall_conflict_sets_offset =
- be32_to_cpu(chwall_buf->chwall_conflict_sets_offset);
- chwall_buf->chwall_running_types_offset =
- be32_to_cpu(chwall_buf->chwall_running_types_offset);
- chwall_buf->chwall_conflict_aggregate_offset =
- be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset);
-
- /* policy type and version checks */
- if ( (chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
- (chwall_buf->policy_version != ACM_CHWALL_VERSION) )
- return -EINVAL;
-
- /* during boot dom0_chwall_ssidref is set */
- if ( is_bootpolicy &&
- (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs) )
- return -EINVAL;
-
- return _chwall_update_policy(buf, buf_size, 1, errors);
-}
-
-static int chwall_set_policy(u8 *buf, u32 buf_size)
-{
- return _chwall_update_policy(buf, buf_size, 0, NULL);
-}
-
-static int chwall_dump_stats(u8 * buf, u16 len)
-{
- /* no stats for Chinese Wall Policy */
- return 0;
-}
-
-static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
-{
- int i;
-
- /* fill in buffer */
- if ( chwall_bin_pol.max_types > len )
- return -EFAULT;
-
- if ( ssidref >= chwall_bin_pol.max_ssidrefs )
- return -EFAULT;
-
- /* read types for chwall ssidref */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- {
- if ( chwall_bin_pol.
- ssidrefs[ssidref * chwall_bin_pol.max_types + i] )
- buf[i] = 1;
- else
- buf[i] = 0;
- }
- return chwall_bin_pol.max_types;
-}
-
-/***************************
- * Authorization functions
- ***************************/
-
-/* -------- DOMAIN OPERATION HOOKS -----------*/
-
-static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
-{
- ssidref_t chwall_ssidref;
- int i, j;
-
- chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
-
- if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs )
- {
- printk("%s: ERROR chwall_ssidref > max(%x).\n",
- __func__, chwall_bin_pol.max_ssidrefs - 1);
- return ACM_ACCESS_DENIED;
- }
-
- /* A: chinese wall check for conflicts */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- if ( chwall_bin_pol.conflict_aggregate_set[i] &&
- chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + i] )
- {
- printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
- return ACM_ACCESS_DENIED;
- }
-
- /* B: chinese wall conflict set adjustment (so that other
- * other domains simultaneously created are evaluated against
- * this new set)
- */
- for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
- {
- int common = 0;
- /* check if conflict_set_i and ssidref have common types */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.
- conflict_sets[i * chwall_bin_pol.max_types + j]
- && chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j] )
- {
- common = 1;
- break;
- }
- if ( common == 0 )
- continue; /* try next conflict set */
- /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.
- conflict_sets[i * chwall_bin_pol.max_types + j]
- && !chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j])
- chwall_bin_pol.conflict_aggregate_set[j]++;
- }
- return ACM_ACCESS_PERMITTED;
-}
-
-
-static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
-{
- int i;
- ssidref_t chwall_ssidref;
-
- chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
- /* adjust types ref-count for running domains */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- chwall_bin_pol.running_types[i] +=
- chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + i];
-}
-
-
-/*
- * To be called when creating a domain. If this call is unsuccessful,
- * no state changes have occurred (adjustments of counters etc.). If it
- * was successful, state was changed and can be undone using
- * chwall_domain_destroy.
- */
-static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref,
- domid_t domid)
-{
- int rc;
- read_lock(&acm_bin_pol_rwlock);
-
- rc = _chwall_pre_domain_create(subject_ssid, ssidref);
- if ( rc == ACM_ACCESS_PERMITTED )
- _chwall_post_domain_create(domid, ssidref);
-
- read_unlock(&acm_bin_pol_rwlock);
- return rc;
-}
-
-/*
- * This function undoes everything a successful call to
- * chwall_domain_create has done.
- */
-static void chwall_domain_destroy(void *object_ssid, struct domain *d)
-{
- int i, j;
- struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
- (struct acm_ssid_domain *)
- object_ssid);
- ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
-
- read_lock(&acm_bin_pol_rwlock);
-
- /* adjust running types set */
- for ( i = 0; i < chwall_bin_pol.max_types; i++ )
- chwall_bin_pol.running_types[i] -=
- chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + i];
-
- /* roll-back: re-adjust conflicting types aggregate */
- for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ )
- {
- int common = 0;
- /* check if conflict_set_i and ssidref have common types */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.conflict_sets[i * chwall_bin_pol.max_types + j]
- && chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j])
- {
- common = 1;
- break;
- }
- if ( common == 0 )
- {
- /* try next conflict set, this one does not include
- any type of chwall_ssidref */
- continue;
- }
-
- /* now add types of the conflict set to conflict_aggregate_set
- (except types in chwall_ssidref) */
- for ( j = 0; j < chwall_bin_pol.max_types; j++ )
- if ( chwall_bin_pol.
- conflict_sets[i * chwall_bin_pol.max_types + j]
- && !chwall_bin_pol.ssidrefs[chwall_ssidref *
- chwall_bin_pol.max_types + j])
- chwall_bin_pol.conflict_aggregate_set[j]--;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return;
-}
-
-
-static int chwall_is_default_policy(void)
-{
- static const domaintype_t def_policy[2] = { 0x0, 0x0 };
- return ( ( chwall_bin_pol.max_types == 1 ) &&
- ( chwall_bin_pol.max_ssidrefs == 2 ) &&
- ( memcmp(chwall_bin_pol.ssidrefs,
- def_policy,
- sizeof(def_policy)) == 0 ) );
-}
-
-
-static int chwall_is_in_conflictset(ssidref_t ssidref1)
-{
- /* is ssidref1 in conflict with any running domains ? */
- int rc = 0;
- int i, j;
- ssidref_t ssid_chwall;
-
- read_lock(&acm_bin_pol_rwlock);
-
- ssid_chwall = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref1);
-
- if ( ssid_chwall >= 0 && ssid_chwall < chwall_bin_pol.max_ssidrefs ) {
- for ( i = 0; i < chwall_bin_pol.max_conflictsets && rc == 0; i++ ) {
- for ( j = 0; j < chwall_bin_pol.max_types; j++ ) {
- if ( chwall_bin_pol.conflict_aggregate_set
- [i * chwall_bin_pol.max_types + j] &&
- chwall_bin_pol.ssidrefs
- [ssid_chwall * chwall_bin_pol.max_types + j])
- {
- rc = 1;
- break;
- }
- }
- }
- } else {
- rc = 1;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return rc;
-}
-
-
-struct acm_operations acm_chinesewall_ops = {
- /* policy management services */
- .init_domain_ssid = chwall_init_domain_ssid,
- .free_domain_ssid = chwall_free_domain_ssid,
- .dump_binary_policy = chwall_dump_policy,
- .test_binary_policy = chwall_test_policy,
- .set_binary_policy = chwall_set_policy,
- .dump_statistics = chwall_dump_stats,
- .dump_ssid_types = chwall_dump_ssid_types,
- /* domain management control hooks */
- .domain_create = chwall_domain_create,
- .domain_destroy = chwall_domain_destroy,
- /* event channel control hooks */
- .pre_eventchannel_unbound = NULL,
- .fail_eventchannel_unbound = NULL,
- .pre_eventchannel_interdomain = NULL,
- .fail_eventchannel_interdomain = NULL,
- /* grant table control hooks */
- .pre_grant_map_ref = NULL,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = NULL,
- .fail_grant_setup = NULL,
- /* generic domain-requested decision hooks */
- .sharing = NULL,
- .authorization = NULL,
- .conflictset = chwall_is_in_conflictset,
-
- .is_default_policy = chwall_is_default_policy,
-};
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_core.c b/xen/xsm/acm/acm_core.c
deleted file mode 100644
index b8b7b4f59c..0000000000
--- a/xen/xsm/acm/acm_core.c
+++ /dev/null
@@ -1,406 +0,0 @@
-#/****************************************************************
- * acm_core.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype access control module (ACM)
- * This file handles initialization of the ACM
- * as well as initializing/freeing security
- * identifiers for domains (it calls on active
- * policy hook functions).
- *
- */
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <xen/multiboot.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-#include <xsm/xsm.h>
-
-/* debug:
- * include/xsm/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
- * define/undefine this constant to receive / suppress any
- * security hook debug output of sHype
- *
- * include/xsm/acm/acm_hooks.h defines a constant ACM_DEBUG
- * define/undefine this constant to receive non-hook-related
- * debug output.
- */
-
-/* function prototypes */
-void acm_init_chwall_policy(void);
-void acm_init_ste_policy(void);
-
-extern struct acm_operations acm_chinesewall_ops,
- acm_simple_type_enforcement_ops, acm_null_ops;
-
-extern struct xsm_operations acm_xsm_ops;
-
-/* global ACM policy (now dynamically determined at boot time) */
-u16 acm_active_security_policy = ACM_POLICY_UNDEFINED;
-
-/* global ops structs called by the hooks */
-struct acm_operations *acm_primary_ops = NULL;
-/* called in hook if-and-only-if primary succeeds */
-struct acm_operations *acm_secondary_ops = NULL;
-
-/* acm global binary policy (points to 'local' primary and secondary policies */
-struct acm_binary_policy acm_bin_pol;
-/* acm binary policy lock */
-DEFINE_RWLOCK(acm_bin_pol_rwlock);
-
-/* ACM's only accepted policy name during boot */
-char polname[80];
-char *acm_accepted_boot_policy_name = NULL;
-
-/* a lits of all chained ssid structures */
-LIST_HEAD(ssid_list);
-DEFINE_RWLOCK(ssid_list_rwlock);
-
-static void __init set_dom0_ssidref(const char *val)
-{
- /* expected format:
- ssidref=<hex number>:<policy name>
- Policy name must not have a 'space'.
- */
- const char *c;
- int lo, hi;
- int i;
- int dom0_ssidref = simple_strtoull(val, &c, 0);
-
- if (!strncmp(&c[0],":ACM:", 5)) {
- lo = dom0_ssidref & 0xffff;
- if (lo < ACM_MAX_NUM_TYPES && lo >= 1)
- dom0_chwall_ssidref = lo;
- hi = dom0_ssidref >> 16;
- if (hi < ACM_MAX_NUM_TYPES && hi >= 1)
- dom0_ste_ssidref = hi;
- for (i = 0; i < sizeof(polname); i++) {
- polname[i] = c[5+i];
- if (polname[i] == '\0' || polname[i] == '\t' ||
- polname[i] == '\n' || polname[i] == ' ' ||
- polname[i] == ':') {
- break;
- }
- }
- polname[i] = 0;
- acm_accepted_boot_policy_name = polname;
- }
-}
-
-custom_param("ssidref", set_dom0_ssidref);
-
-int
-acm_set_policy_reference(u8 *buf, u32 buf_size)
-{
- char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer));
- struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
-
- if (acm_accepted_boot_policy_name != NULL) {
- if (strcmp(acm_accepted_boot_policy_name, name)) {
- printk("Policy's name '%s' is not the expected one '%s'.\n",
- name, acm_accepted_boot_policy_name);
- return ACM_ERROR;
- }
- }
-
- acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len));
-
- if (!acm_bin_pol.policy_reference_name)
- return -ENOMEM;
- strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len));
-
- printk("%s: Activating policy %s\n", __func__,
- acm_bin_pol.policy_reference_name);
- return 0;
-}
-
-int
-acm_dump_policy_reference(u8 *buf, u32 buf_size)
-{
- struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
- int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
-
- ret = (ret + 7) & ~7;
- if (buf_size < ret)
- return -EINVAL;
-
- memset(buf, 0, ret);
- pr_buf->len = cpu_to_be32(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
- strlcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
- acm_bin_pol.policy_reference_name,
- be32_to_cpu(pr_buf->len));
- return ret;
-}
-
-int
-acm_init_binary_policy(u32 policy_code)
-{
- int ret = ACM_OK;
-
- acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
- acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
-
- write_lock(&acm_bin_pol_rwlock);
-
- /* set primary policy component */
- switch ((policy_code) & 0x0f)
- {
-
- case ACM_CHINESE_WALL_POLICY:
- acm_init_chwall_policy();
- acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
- acm_primary_ops = &acm_chinesewall_ops;
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- acm_init_ste_policy();
- acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
- acm_primary_ops = &acm_simple_type_enforcement_ops;
- break;
-
- case ACM_NULL_POLICY:
- acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
- acm_primary_ops = &acm_null_ops;
- break;
-
- default:
- /* Unknown policy not allowed primary */
- ret = -EINVAL;
- goto out;
- }
-
- /* secondary policy component part */
- switch ((policy_code) >> 4)
- {
-
- case ACM_NULL_POLICY:
- acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
- acm_secondary_ops = &acm_null_ops;
- break;
-
- case ACM_CHINESE_WALL_POLICY:
- if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
- { /* not a valid combination */
- ret = -EINVAL;
- goto out;
- }
- acm_init_chwall_policy();
- acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
- acm_secondary_ops = &acm_chinesewall_ops;
- break;
-
- case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
- { /* not a valid combination */
- ret = -EINVAL;
- goto out;
- }
- acm_init_ste_policy();
- acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
- acm_secondary_ops = &acm_simple_type_enforcement_ops;
- break;
-
- default:
- ret = -EINVAL;
- goto out;
- }
-
- out:
- write_unlock(&acm_bin_pol_rwlock);
- return ret;
-}
-
-int
-acm_is_policy(char *buf, unsigned long len)
-{
- struct acm_policy_buffer *pol;
-
- if (buf == NULL || len < sizeof(struct acm_policy_buffer))
- return 0;
-
- pol = (struct acm_policy_buffer *)buf;
- return be32_to_cpu(pol->magic) == ACM_MAGIC;
-}
-
-
-static int
-acm_setup(char *policy_start,
- unsigned long policy_len,
- int is_bootpolicy)
-{
- int rc = ACM_OK;
- struct acm_policy_buffer *pol;
-
- if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
- return rc;
-
- pol = (struct acm_policy_buffer *)policy_start;
- if (be32_to_cpu(pol->magic) != ACM_MAGIC)
- return rc;
-
- rc = do_acm_set_policy((void *)policy_start, (u32)policy_len,
- is_bootpolicy,
- NULL, NULL, NULL);
- if (rc == ACM_OK)
- {
- printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start);
- }
- else
- {
- printk("Invalid policy.\n");
- /* load default policy later */
- acm_active_security_policy = ACM_POLICY_UNDEFINED;
- }
- return rc;
-}
-
-
-int
-acm_init(void)
-{
- int ret = ACM_OK;
-
- printk("ACM-XSM: Initializing.\n");
-
- /* first try to load the boot policy (uses its own locks) */
- acm_setup(policy_buffer, policy_size, 1);
-
- /* a user-provided policy may have any name; only matched during boot */
- acm_accepted_boot_policy_name = NULL;
-
- if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
- {
- printk("%s: Enforcing %s boot policy.\n", __func__,
- ACM_POLICY_NAME(acm_active_security_policy));
- goto out;
- }
- /* else continue with the minimal hardcoded default startup policy */
- printk("%s: Loading default policy (%s).\n",
- __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
-
- /* (re-)set dom-0 ssidref to default */
- dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001;
-
- if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
- ret = -EINVAL;
- goto out;
- }
- acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
- if (acm_active_security_policy != ACM_NULL_POLICY)
- acm_bin_pol.policy_reference_name = "DEFAULT";
- else
- acm_bin_pol.policy_reference_name = "NULL";
-
- out:
- if (ret != ACM_OK)
- {
- printk("%s: Error initializing policies.\n", __func__);
- /* here one could imagine a clean panic */
- return -EINVAL;
- }
-
- if (register_xsm(&acm_xsm_ops))
- panic("ACM-XSM: Unable to register with XSM.\n");
-
- return ret;
-}
-
-xsm_initcall(acm_init);
-
-int acm_init_domain_ssid(struct domain *subj, ssidref_t ssidref)
-{
- struct acm_ssid_domain *ssid;
- int ret1, ret2;
- if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
- {
- return ACM_INIT_SSID_ERROR;
- }
-
- INIT_LIST_HEAD(&ssid->node);
- ssid->datatype = ACM_DATATYPE_domain;
- ssid->subject = subj;
- ssid->domainid = subj->domain_id;
- ssid->primary_ssid = NULL;
- ssid->secondary_ssid = NULL;
-
- if (acm_active_security_policy != ACM_NULL_POLICY)
- ssid->ssidref = ssidref;
- else
- ssid->ssidref = ACM_DEFAULT_SSID;
-
- subj->ssid = ssid;
- /* now fill in primary and secondary parts; we only get here through hooks */
- if (acm_primary_ops->init_domain_ssid != NULL)
- ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
- else
- ret1 = ACM_OK;
-
- if (acm_secondary_ops->init_domain_ssid != NULL)
- ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
- else
- ret2 = ACM_OK;
-
- if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
- {
- printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
- __func__, subj->domain_id);
- acm_free_domain_ssid(subj);
- return ACM_INIT_SSID_ERROR;
- }
-
- printkd("%s: assigned domain %x the ssidref=%x.\n",
- __func__, subj->domain_id, ssid->ssidref);
- return ACM_OK;
-}
-
-
-void
-acm_free_domain_ssid(struct domain *d)
-{
- struct acm_ssid_domain *ssid = d->ssid;
-
- /* domain is already gone, just ssid is left */
- if (ssid == NULL)
- return;
-
- ssid->subject = NULL;
- if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
- acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
- ssid->primary_ssid = NULL;
- if (acm_secondary_ops->free_domain_ssid != NULL)
- acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
- ssid->secondary_ssid = NULL;
-
- xfree(ssid);
- d->ssid = NULL;
-
- printkd("%s: Freed individual domain ssid (domain=%02x).\n",
- __func__, id);
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_null_hooks.c b/xen/xsm/acm/acm_null_hooks.c
deleted file mode 100644
index 440ee61bd8..0000000000
--- a/xen/xsm/acm/acm_null_hooks.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************
- * acm_null_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-
-#include <xsm/acm/acm_hooks.h>
-
-static int
-null_init_domain_ssid(void **ssid, ssidref_t ssidref)
-{
- return ACM_OK;
-}
-
-static void
-null_free_domain_ssid(void *ssid)
-{
- return;
-}
-
-static int
-null_dump_binary_policy(u8 *buf, u32 buf_size)
-{
- return 0;
-}
-
-static int
-null_test_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *errors)
-{
- return ACM_OK;
-}
-
-static int
-null_set_binary_policy(u8 *buf, u32 buf_size)
-{
- return ACM_OK;
-}
-
-static int
-null_dump_stats(u8 *buf, u16 buf_size)
-{
- /* no stats for NULL policy */
- return 0;
-}
-
-static int
-null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
-{
- /* no types */
- return 0;
-}
-
-
-/* now define the hook structure similarly to LSM */
-struct acm_operations acm_null_ops = {
- .init_domain_ssid = null_init_domain_ssid,
- .free_domain_ssid = null_free_domain_ssid,
- .dump_binary_policy = null_dump_binary_policy,
- .test_binary_policy = null_test_binary_policy,
- .set_binary_policy = null_set_binary_policy,
- .dump_statistics = null_dump_stats,
- .dump_ssid_types = null_dump_ssid_types,
- /* domain management control hooks */
- .domain_create = NULL,
- .domain_destroy = NULL,
- /* event channel control hooks */
- .pre_eventchannel_unbound = NULL,
- .fail_eventchannel_unbound = NULL,
- .pre_eventchannel_interdomain = NULL,
- .fail_eventchannel_interdomain = NULL,
- /* grant table control hooks */
- .pre_grant_map_ref = NULL,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = NULL,
- .fail_grant_setup = NULL
-};
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_ops.c b/xen/xsm/acm/acm_ops.c
deleted file mode 100644
index 5836241a98..0000000000
--- a/xen/xsm/acm/acm_ops.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/******************************************************************************
- * acm_ops.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * Process acm command requests from guest OS.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <public/xsm/acm.h>
-#include <public/xsm/acm_ops.h>
-#include <xen/sched.h>
-#include <xen/event.h>
-#include <xen/trace.h>
-#include <xen/console.h>
-#include <xen/guest_access.h>
-#include <xsm/acm/acm_hooks.h>
-
-#ifndef ACM_SECURITY
-
-long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
-{
- return -ENOSYS;
-}
-
-#else
-
-int acm_authorize_acm_ops(struct domain *d)
-{
- /* currently, policy management functions are restricted to privileged domains */
- return (IS_PRIV(d) ? 0 : -EPERM);
-}
-
-
-long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
-{
- long rc = -EFAULT;
- struct xen_acmctl curop, *op = &curop;
-
- if (acm_authorize_acm_ops(current->domain))
- return -EPERM;
-
- if ( copy_from_guest(op, u_acmctl, 1) )
- return -EFAULT;
-
- if (op->interface_version != ACM_INTERFACE_VERSION)
- return -EACCES;
-
- switch ( op->cmd )
- {
-
- case ACMOP_setpolicy: {
- rc = acm_set_policy(op->u.setpolicy.pushcache,
- op->u.setpolicy.pushcache_size);
- break;
- }
-
- case ACMOP_getpolicy: {
- rc = acm_get_policy(op->u.getpolicy.pullcache,
- op->u.getpolicy.pullcache_size);
- break;
- }
-
- case ACMOP_dumpstats: {
- rc = acm_dump_statistics(op->u.dumpstats.pullcache,
- op->u.dumpstats.pullcache_size);
- break;
- }
-
- case ACMOP_getssid: {
- ssidref_t ssidref;
-
- if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
- ssidref = op->u.getssid.id.ssidref;
- else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
- {
- struct domain *subj = rcu_lock_domain_by_id(op->u.getssid.id.domainid);
- if (!subj)
- {
- rc = -ESRCH; /* domain not found */
- break;
- }
- if (subj->ssid == NULL)
- {
- rcu_unlock_domain(subj);
- rc = -ESRCH;
- break;
- }
- ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
- rcu_unlock_domain(subj);
- }
- else
- {
- rc = -ESRCH;
- break;
- }
- rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
- op->u.getssid.ssidbuf_size);
- break;
- }
-
- case ACMOP_getdecision: {
- ssidref_t ssidref1, ssidref2;
-
- if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
- ssidref1 = op->u.getdecision.id1.ssidref;
- else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
- {
- struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
- if (!subj)
- {
- rc = -ESRCH; /* domain not found */
- break;
- }
- if (subj->ssid == NULL)
- {
- rcu_unlock_domain(subj);
- rc = -ESRCH;
- break;
- }
- ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
- rcu_unlock_domain(subj);
- }
- else
- {
- rc = -ESRCH;
- break;
- }
- if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
- ssidref2 = op->u.getdecision.id2.ssidref;
- else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
- {
- struct domain *subj = rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
- if (!subj)
- {
- rc = -ESRCH; /* domain not found */
- break;
- }
- if (subj->ssid == NULL)
- {
- rcu_unlock_domain(subj);
- rc = -ESRCH;
- break;
- }
- ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
- rcu_unlock_domain(subj);
- }
- else
- {
- rc = -ESRCH;
- break;
- }
- rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
-
- if (rc == ACM_ACCESS_PERMITTED)
- {
- op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
- rc = 0;
- }
- else if (rc == ACM_ACCESS_DENIED)
- {
- op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
- rc = 0;
- }
- else
- rc = -ESRCH;
-
- if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
- rc = -EFAULT;
- break;
- }
-
- case ACMOP_chgpolicy: {
- rc = acm_change_policy(&op->u.change_policy);
- break;
- }
-
- case ACMOP_relabeldoms: {
- rc = acm_relabel_domains(&op->u.relabel_doms);
- break;
- }
-
- default:
- rc = -ENOSYS;
- break;
- }
-
- return rc;
-}
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_policy.c b/xen/xsm/acm/acm_policy.c
deleted file mode 100644
index 31219d9aae..0000000000
--- a/xen/xsm/acm/acm_policy.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/****************************************************************
- * acm_policy.c
- *
- * Copyright (C) 2005-2007 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Stefan Berger <stefanb@watson.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype access control policy management for Xen.
- * This interface allows policy tools in authorized
- * domains to interact with the Xen access control module
- *
- */
-
-#include <xen/config.h>
-#include <xen/errno.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/delay.h>
-#include <xen/sched.h>
-#include <xen/guest_access.h>
-#include <public/xen.h>
-#include <xsm/acm/acm_core.h>
-#include <public/xsm/acm_ops.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-#include <asm/current.h>
-
-static int acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
- struct acm_sized_buffer *errors);
-static void acm_doms_change_ssidref(ssidref_t (*translator)
- (const struct acm_ssid_domain *,
- const struct acm_sized_buffer *),
- struct acm_sized_buffer *translation_map);
-static void acm_doms_restore_ssidref(void);
-static ssidref_t oldssid_to_newssid(const struct acm_ssid_domain *,
- const struct acm_sized_buffer *map);
-
-
-int
-acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
-{
- u8 *policy_buffer = NULL;
- int ret = -EFAULT;
-
- if ( buf_size < sizeof(struct acm_policy_buffer) )
- return -EFAULT;
-
- /* copy buffer from guest domain */
- if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- if ( copy_from_guest(policy_buffer, buf, buf_size) )
- {
- printk("%s: Error copying!\n",__func__);
- goto error_free;
- }
- ret = do_acm_set_policy(policy_buffer, buf_size, 0,
- NULL, NULL, NULL);
-
- error_free:
- xfree(policy_buffer);
- return ret;
-}
-
-
-/*
- * Update the policy of the running system by:
- * - deleting ssidrefs that are not in the new policy anymore
- * -> no running domain may use such an ssidref
- * - assign new ssidrefs to domains based on their old ssidrefs
- *
- */
-static int
-_acm_update_policy(void *buf, u32 buf_size, int is_bootpolicy,
- struct acm_policy_buffer *pol,
- struct acm_sized_buffer *deletions,
- struct acm_sized_buffer *ssidchanges,
- struct acm_sized_buffer *errors)
-{
- uint32_t offset, length;
- static int require_update = 0;
-
- write_lock(&acm_bin_pol_rwlock);
-
- if ( require_update != 0 &&
- ( deletions == NULL || ssidchanges == NULL ) )
- goto error_lock_free;
-
- require_update = 1;
- /*
- first some tests to check compatibility of new policy with
- current state of system/domains
- */
-
- /* if ssidrefs are to be deleted, make sure no domain is using them */
- if ( deletions != NULL )
- if ( acm_check_deleted_ssidrefs(deletions, errors) )
- goto error_lock_free_nossidchange;
-
- if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
- /* assign all running domains new ssidrefs as requested */
- acm_doms_change_ssidref(oldssid_to_newssid, ssidchanges);
-
- /* test primary policy data with the new ssidrefs */
- offset = be32_to_cpu(pol->primary_buffer_offset);
- length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
-
- if ( (offset + length) > buf_size ||
- acm_primary_ops->test_binary_policy(buf + offset, length,
- is_bootpolicy,
- errors))
- goto error_lock_free;
-
- /* test secondary policy data with the new ssidrefs */
- offset = be32_to_cpu(pol->secondary_buffer_offset);
- length = be32_to_cpu(pol->len) - offset;
- if ( (offset + length) > buf_size ||
- acm_secondary_ops->test_binary_policy(buf + offset, length,
- is_bootpolicy,
- errors))
- goto error_lock_free;
-
- /* end of testing --- now real updates */
-
- offset = be32_to_cpu(pol->policy_reference_offset);
- length = be32_to_cpu(pol->primary_buffer_offset) - offset;
-
- /* set label reference name */
- if ( (offset + length) > buf_size ||
- acm_set_policy_reference(buf + offset, length) )
- goto error_lock_free;
-
- /* set primary policy data */
- offset = be32_to_cpu(pol->primary_buffer_offset);
- length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
-
- if ( acm_primary_ops->set_binary_policy(buf + offset, length) )
- goto error_lock_free;
-
- /* set secondary policy data */
- offset = be32_to_cpu(pol->secondary_buffer_offset);
- length = be32_to_cpu(pol->len) - offset;
- if ( acm_secondary_ops->set_binary_policy(buf + offset, length) )
- goto error_lock_free;
-
- memcpy(&acm_bin_pol.xml_pol_version,
- &pol->xml_pol_version,
- sizeof(acm_bin_pol.xml_pol_version));
-
- memcpy(&acm_bin_pol.xml_policy_hash,
- pol->xml_policy_hash,
- sizeof(acm_bin_pol.xml_policy_hash));
-
- if ( acm_primary_ops->is_default_policy() &&
- acm_secondary_ops->is_default_policy() )
- require_update = 0;
-
- write_unlock(&acm_bin_pol_rwlock);
-
- return ACM_OK;
-
-error_lock_free:
- if ( (ssidchanges != NULL) && (ssidchanges->num_items > 0) )
- {
- acm_doms_restore_ssidref();
- }
-error_lock_free_nossidchange:
- do_chwall_init_state_curr(NULL);
- write_unlock(&acm_bin_pol_rwlock);
-
- return -EFAULT;
-}
-
-
-int
-do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *deletions,
- struct acm_sized_buffer *ssidchanges,
- struct acm_sized_buffer *errors)
-{
- struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
-
- /* some sanity checking */
- if ( (be32_to_cpu(pol->magic) != ACM_MAGIC) ||
- (buf_size != be32_to_cpu(pol->len)) ||
- (be32_to_cpu(pol->policy_version) != ACM_POLICY_VERSION) )
- {
- printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
- goto error_free;
- }
-
- if ( acm_active_security_policy == ACM_POLICY_UNDEFINED )
- {
- /* setup the policy with the boot policy */
- if ( acm_init_binary_policy(
- (be32_to_cpu(pol->secondary_policy_code) << 4) |
- be32_to_cpu(pol->primary_policy_code)) )
- {
- goto error_free;
- }
- acm_active_security_policy = (acm_bin_pol.secondary_policy_code << 4) |
- acm_bin_pol.primary_policy_code;
- }
-
- /* once acm_active_security_policy is set, it cannot be changed */
- if ( (be32_to_cpu(pol->primary_policy_code) !=
- acm_bin_pol.primary_policy_code) ||
- (be32_to_cpu(pol->secondary_policy_code) !=
- acm_bin_pol.secondary_policy_code) )
- {
- printkd("%s: Wrong policy type in boot policy!\n", __func__);
- goto error_free;
- }
-
- return _acm_update_policy(buf, buf_size, is_bootpolicy,
- pol,
- deletions, ssidchanges,
- errors);
-
- error_free:
- printk("%s: Error setting policy.\n", __func__);
- return -EFAULT;
-}
-
-int
-acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size)
-{
- u8 *policy_buffer;
- int ret;
- struct acm_policy_buffer *bin_pol;
-
- if ( buf_size < sizeof(struct acm_policy_buffer) )
- return -EFAULT;
-
- if ( (policy_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- read_lock(&acm_bin_pol_rwlock);
-
- bin_pol = (struct acm_policy_buffer *)policy_buffer;
- bin_pol->magic = cpu_to_be32(ACM_MAGIC);
- bin_pol->primary_policy_code =
- cpu_to_be32(acm_bin_pol.primary_policy_code);
- bin_pol->secondary_policy_code =
- cpu_to_be32(acm_bin_pol.secondary_policy_code);
-
- bin_pol->len = cpu_to_be32(sizeof(struct acm_policy_buffer));
- bin_pol->policy_reference_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
- bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
- bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
-
- memcpy(&bin_pol->xml_pol_version,
- &acm_bin_pol.xml_pol_version,
- sizeof(struct acm_policy_version));
-
- memcpy(&bin_pol->xml_policy_hash,
- &acm_bin_pol.xml_policy_hash,
- sizeof(acm_bin_pol.xml_policy_hash));
-
- ret = acm_dump_policy_reference(
- policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset),
- buf_size - be32_to_cpu(bin_pol->policy_reference_offset));
-
- if ( ret < 0 )
- goto error_free_unlock;
-
- bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
- bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
-
- ret = acm_primary_ops->dump_binary_policy(
- policy_buffer + be32_to_cpu(bin_pol->primary_buffer_offset),
- buf_size - be32_to_cpu(bin_pol->primary_buffer_offset));
-
- if ( ret < 0 )
- goto error_free_unlock;
-
- bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
- bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
-
- ret = acm_secondary_ops->dump_binary_policy(
- policy_buffer + be32_to_cpu(bin_pol->secondary_buffer_offset),
- buf_size - be32_to_cpu(bin_pol->secondary_buffer_offset));
-
- if ( ret < 0 )
- goto error_free_unlock;
-
- bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
- if ( copy_to_guest(buf, policy_buffer, be32_to_cpu(bin_pol->len)) )
- goto error_free_unlock;
-
- read_unlock(&acm_bin_pol_rwlock);
- xfree(policy_buffer);
-
- return ACM_OK;
-
- error_free_unlock:
- read_unlock(&acm_bin_pol_rwlock);
- printk("%s: Error getting policy.\n", __func__);
- xfree(policy_buffer);
-
- return -EFAULT;
-}
-
-int
-acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
-{
- /* send stats to user space */
- u8 *stats_buffer;
- int len1, len2;
- struct acm_stats_buffer acm_stats;
-
- if ( (stats_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- read_lock(&acm_bin_pol_rwlock);
-
- len1 = acm_primary_ops->dump_statistics(
- stats_buffer + sizeof(struct acm_stats_buffer),
- buf_size - sizeof(struct acm_stats_buffer));
- if ( len1 < 0 )
- goto error_lock_free;
-
- len2 = acm_secondary_ops->dump_statistics(
- stats_buffer + sizeof(struct acm_stats_buffer) + len1,
- buf_size - sizeof(struct acm_stats_buffer) - len1);
- if ( len2 < 0 )
- goto error_lock_free;
-
- acm_stats.magic = cpu_to_be32(ACM_MAGIC);
- acm_stats.primary_policy_code =
- cpu_to_be32(acm_bin_pol.primary_policy_code);
- acm_stats.secondary_policy_code =
- cpu_to_be32(acm_bin_pol.secondary_policy_code);
- acm_stats.primary_stats_offset =
- cpu_to_be32(sizeof(struct acm_stats_buffer));
- acm_stats.secondary_stats_offset =
- cpu_to_be32(sizeof(struct acm_stats_buffer) + len1);
- acm_stats.len = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1 + len2);
-
- memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
-
- if ( copy_to_guest(buf,
- stats_buffer,
- sizeof(struct acm_stats_buffer) + len1 + len2) )
- goto error_lock_free;
-
- read_unlock(&acm_bin_pol_rwlock);
- xfree(stats_buffer);
-
- return ACM_OK;
-
- error_lock_free:
- read_unlock(&acm_bin_pol_rwlock);
- xfree(stats_buffer);
-
- return -EFAULT;
-}
-
-
-int
-acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size)
-{
- /* send stats to user space */
- u8 *ssid_buffer;
- int ret;
- struct acm_ssid_buffer *acm_ssid;
- if ( buf_size < sizeof(struct acm_ssid_buffer) )
- return -EFAULT;
-
- if ( (ssid_buffer = xmalloc_array(u8, buf_size)) == NULL )
- return -ENOMEM;
-
- read_lock(&acm_bin_pol_rwlock);
-
- acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
- acm_ssid->len = sizeof(struct acm_ssid_buffer);
- acm_ssid->ssidref = ssidref;
- acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
- acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
-
- acm_ssid->policy_reference_offset = acm_ssid->len;
- ret = acm_dump_policy_reference(
- ssid_buffer + acm_ssid->policy_reference_offset,
- buf_size - acm_ssid->policy_reference_offset);
- if ( ret < 0 )
- goto error_free_unlock;
-
- acm_ssid->len += ret;
- acm_ssid->primary_types_offset = acm_ssid->len;
-
- /* ret >= 0 --> ret == max_types */
- ret = acm_primary_ops->dump_ssid_types(
- ACM_PRIMARY(ssidref),
- ssid_buffer + acm_ssid->primary_types_offset,
- buf_size - acm_ssid->primary_types_offset);
- if ( ret < 0 )
- goto error_free_unlock;
-
- acm_ssid->len += ret;
- acm_ssid->primary_max_types = ret;
- acm_ssid->secondary_types_offset = acm_ssid->len;
-
- ret = acm_secondary_ops->dump_ssid_types(
- ACM_SECONDARY(ssidref),
- ssid_buffer + acm_ssid->secondary_types_offset,
- buf_size - acm_ssid->secondary_types_offset);
- if ( ret < 0 )
- goto error_free_unlock;
-
- acm_ssid->len += ret;
- acm_ssid->secondary_max_types = ret;
-
- if ( copy_to_guest(buf, ssid_buffer, acm_ssid->len) )
- goto error_free_unlock;
-
- read_unlock(&acm_bin_pol_rwlock);
- xfree(ssid_buffer);
-
- return ACM_OK;
-
- error_free_unlock:
- read_unlock(&acm_bin_pol_rwlock);
- printk("%s: Error getting ssid.\n", __func__);
- xfree(ssid_buffer);
-
- return -ENOMEM;
-}
-
-int
-acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook)
-{
- int ret = ACM_ACCESS_DENIED;
-
- read_lock(&acm_bin_pol_rwlock);
-
- switch ( hook )
- {
-
- case ACMHOOK_sharing:
- /* Sharing hook restricts access in STE policy only */
- ret = acm_sharing(ssidref1, ssidref2);
- break;
-
- case ACMHOOK_authorization:
- ret = acm_authorization(ssidref1, ssidref2);
- break;
-
- case ACMHOOK_conflictset:
- ret = acm_conflictset(ssidref1);
-
- default:
- /* deny */
- break;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n",
- __func__, ssidref1, ssidref2,
- (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED");
-
- return ret;
-}
-
-
-
-/*
- Check if an ssidref of the current policy type is being used by any
- domain.
- */
-static int
-acm_check_used_ssidref(uint32_t policy_type, uint32_t search_ssidref,
- struct acm_sized_buffer *errors)
-{
- int rc = 0;
- struct acm_ssid_domain *rawssid;
-
- read_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ssidref_t ssidref;
- void *s = GET_SSIDP(policy_type, rawssid);
-
- if ( policy_type == ACM_CHINESE_WALL_POLICY )
- {
- ssidref = ((struct chwall_ssid *)s)->chwall_ssidref;
- } else {
- ssidref = ((struct ste_ssid *)s)->ste_ssidref;
- }
- gdprintk(XENLOG_INFO,"domid=%d: search ssidref=%d, ssidref=%d\n",
- rawssid->domainid,search_ssidref,ssidref);
- if ( ssidref == search_ssidref )
- {
- /* one is enough */
- acm_array_append_tuple(errors, ACM_SSIDREF_IN_USE, search_ssidref);
- rc = 1;
- break;
- }
- }
-
- read_unlock(&ssid_list_rwlock);
-
- return rc;
-}
-
-
-/*
- * Translate a current ssidref into its future representation under
- * the new policy.
- * The map provides translation of ssidrefs from old to new in tuples
- * of (old ssidref, new ssidref).
- */
-static ssidref_t
-oldssid_to_newssid(const struct acm_ssid_domain *rawssid,
- const struct acm_sized_buffer *map)
-{
- uint i;
-
- if ( rawssid != NULL )
- {
- ssidref_t ssid = rawssid->ssidref & 0xffff;
- for ( i = 0; i + 1 < map->num_items; i += 2 )
- {
- if ( map->array[i] == ssid )
- {
- return (map->array[i+1] << 16 | map->array[i+1]);
- }
- }
- }
- return ACM_INVALID_SSIDREF;
-}
-
-
-/*
- * Assign an ssidref to the CHWALL policy component of the domain
- */
-static void
-acm_pri_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
- ssidref_t new_ssid)
-{
- struct chwall_ssid *chwall = (struct chwall_ssid *)rawssid->primary_ssid;
- chwall->chwall_ssidref = new_ssid;
-}
-
-
-/*
- * Assign an ssidref to the STE policy component of the domain
- */
-static void
-acm_sec_policy_assign_ssidref(struct acm_ssid_domain *rawssid,
- ssidref_t new_ssid)
-{
- struct ste_ssid *ste = (struct ste_ssid *)rawssid->secondary_ssid;
- ste->ste_ssidref = new_ssid;
-}
-
-/*
- Change the ssidrefs on each domain using a passed translation function;
- */
-static void
-acm_doms_change_ssidref(ssidref_t (*translator_fn)
- (const struct acm_ssid_domain *,
- const struct acm_sized_buffer *),
- struct acm_sized_buffer *translation_map)
-{
- struct acm_ssid_domain *rawssid;
-
- write_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ssidref_t new_ssid;
-
- rawssid->old_ssidref = rawssid->ssidref;
-
- new_ssid = translator_fn(rawssid, translation_map);
- if ( new_ssid == ACM_INVALID_SSIDREF )
- {
- /* means no mapping found, so no change -- old = new */
- continue;
- }
-
- acm_pri_policy_assign_ssidref(rawssid, ACM_PRIMARY (new_ssid) );
- acm_sec_policy_assign_ssidref(rawssid, ACM_SECONDARY(new_ssid) );
-
- rawssid->ssidref = new_ssid;
- }
-
- write_unlock(&ssid_list_rwlock);
-}
-
-/*
- * Restore the previous ssidref values on all domains
- */
-static void
-acm_doms_restore_ssidref(void)
-{
- struct acm_ssid_domain *rawssid;
-
- write_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ssidref_t old_ssid;
-
- if ( rawssid->old_ssidref == rawssid->ssidref )
- continue;
-
- old_ssid = rawssid->old_ssidref & 0xffff;
- rawssid->ssidref = rawssid->old_ssidref;
-
- acm_pri_policy_assign_ssidref(rawssid, old_ssid);
- acm_sec_policy_assign_ssidref(rawssid, old_ssid);
- }
-
- write_unlock(&ssid_list_rwlock);
-}
-
-
-/*
- Check the list of domains whether either one of them uses a
- to-be-deleted ssidref.
- */
-static int
-acm_check_deleted_ssidrefs(struct acm_sized_buffer *dels,
- struct acm_sized_buffer *errors)
-{
- int rc = 0;
- uint idx;
- /* check for running domains that should not be there anymore */
- for ( idx = 0; idx < dels->num_items; idx++ )
- {
- if ( acm_check_used_ssidref(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- dels->array[idx],
- errors) > 0 ||
- acm_check_used_ssidref(ACM_CHINESE_WALL_POLICY,
- dels->array[idx],
- errors) > 0)
- {
- rc = ACM_ERROR;
- break;
- }
- }
- return rc;
-}
-
-
-/*
- * Change the policy of the system.
- */
-int
-acm_change_policy(struct acm_change_policy *chgpolicy)
-{
- int rc = 0;
- u8 *binpolicy = NULL;
- struct acm_sized_buffer dels =
- {
- .array = NULL,
- };
- struct acm_sized_buffer ssidmap =
- {
- .array = NULL,
- };
- struct acm_sized_buffer errors =
- {
- .array = NULL,
- };
-
- gdprintk(XENLOG_INFO, "change policy operation\n");
-
- if ( (chgpolicy->delarray_size > 4096) ||
- (chgpolicy->chgarray_size > 4096) ||
- (chgpolicy->errarray_size > 4096))
- {
- return ACM_ERROR;
- }
-
- dels.num_items = chgpolicy->delarray_size / sizeof(uint32_t);
- if ( dels.num_items > 0 )
- {
- dels.array = xmalloc_array(uint32_t, dels.num_items);
- if ( dels.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
- }
-
- ssidmap.num_items = chgpolicy->chgarray_size / sizeof(uint32_t);
- if ( ssidmap.num_items > 0 )
- {
- ssidmap.array = xmalloc_array(uint32_t, ssidmap.num_items);
- if ( ssidmap.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
- }
-
- errors.num_items = chgpolicy->errarray_size / sizeof(uint32_t);
- if ( errors.num_items > 0 )
- {
- errors.array = xmalloc_array(uint32_t, errors.num_items);
- if ( errors.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
- memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
- }
-
- binpolicy = xmalloc_array(u8,
- chgpolicy->policy_pushcache_size);
- if ( binpolicy == NULL )
- {
- rc = -ENOMEM;
- goto acm_chg_policy_exit;
- }
-
- if ( copy_from_guest(dels.array,
- chgpolicy->del_array,
- dels.num_items) ||
- copy_from_guest(ssidmap.array,
- chgpolicy->chg_array,
- ssidmap.num_items) ||
- copy_from_guest(binpolicy,
- chgpolicy->policy_pushcache,
- chgpolicy->policy_pushcache_size ))
- {
- rc = -EFAULT;
- goto acm_chg_policy_exit;
- }
-
- rc = do_acm_set_policy(binpolicy,
- chgpolicy->policy_pushcache_size,
- 0,
- &dels, &ssidmap, &errors);
-
- if ( (errors.num_items > 0) &&
- copy_to_guest(chgpolicy->err_array,
- errors.array,
- errors.num_items ) )
- {
- rc = -EFAULT;
- goto acm_chg_policy_exit;
- }
-
-
-acm_chg_policy_exit:
- xfree(dels.array);
- xfree(ssidmap.array);
- xfree(errors.array);
- xfree(binpolicy);
-
- return rc;
-}
-
-
-/*
- * Lookup the new ssidref given the domain's id.
- * The translation map provides a list of tuples in the format
- * (domid, new ssidref).
- */
-static ssidref_t
-domid_to_newssid(const struct acm_ssid_domain *rawssid,
- const struct acm_sized_buffer *map)
-{
- domid_t domid = rawssid->domainid;
- uint i;
- for ( i = 0; (i+1) < map->num_items; i += 2 )
- {
- if ( map->array[i] == domid )
- return (ssidref_t)map->array[i+1];
- }
- return ACM_INVALID_SSIDREF;
-}
-
-
-int
-do_acm_relabel_doms(struct acm_sized_buffer *relabel_map,
- struct acm_sized_buffer *errors)
-{
- int rc = 0, irc;
-
- write_lock(&acm_bin_pol_rwlock);
-
- acm_doms_change_ssidref(domid_to_newssid, relabel_map);
-
- /* run tests; collect as much error info as possible */
- irc = do_chwall_init_state_curr(errors);
- irc += do_ste_init_state_curr(errors);
- if ( irc != 0 )
- {
- rc = -EFAULT;
- goto acm_relabel_doms_lock_err_exit;
- }
-
- write_unlock(&acm_bin_pol_rwlock);
-
- return rc;
-
-acm_relabel_doms_lock_err_exit:
- /* revert the new ssidref assignment */
- acm_doms_restore_ssidref();
- do_chwall_init_state_curr(NULL);
-
- write_unlock(&acm_bin_pol_rwlock);
-
- return rc;
-}
-
-
-int
-acm_relabel_domains(struct acm_relabel_doms *relabel)
-{
- int rc = ACM_OK;
- struct acm_sized_buffer relabels =
- {
- .array = NULL,
- };
- struct acm_sized_buffer errors =
- {
- .array = NULL,
- };
-
- if ( relabel->relabel_map_size > 4096 )
- {
- return ACM_ERROR;
- }
-
- relabels.num_items = relabel->relabel_map_size / sizeof(uint32_t);
- if ( relabels.num_items > 0 )
- {
- relabels.array = xmalloc_array(uint32_t, relabels.num_items);
- if ( relabels.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_relabel_doms_exit;
- }
- }
-
- errors.num_items = relabel->errarray_size / sizeof(uint32_t);
- if ( errors.num_items > 0 )
- {
- errors.array = xmalloc_array(uint32_t, errors.num_items);
- if ( errors.array == NULL )
- {
- rc = -ENOMEM;
- goto acm_relabel_doms_exit;
- }
- memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items);
- }
-
- if ( copy_from_guest(relabels.array,
- relabel->relabel_map,
- relabels.num_items) )
- {
- rc = -EFAULT;
- goto acm_relabel_doms_exit;
- }
-
- rc = do_acm_relabel_doms(&relabels, &errors);
-
- if ( copy_to_guest(relabel->err_array,
- errors.array,
- errors.num_items ) )
- rc = -EFAULT;
-
-acm_relabel_doms_exit:
- xfree(relabels.array);
- xfree(errors.array);
- return rc;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c
deleted file mode 100644
index 1ceb89fb9c..0000000000
--- a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c
+++ /dev/null
@@ -1,924 +0,0 @@
-/****************************************************************
- * acm_simple_type_enforcement_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Stefan Berger <stefanb@watson.ibm.com>
- * support for network order binary policies
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- * sHype Simple Type Enforcement for Xen
- * STE allows to control which domains can setup sharing
- * (eventchannels right now) with which other domains. Hooks
- * are defined and called throughout Xen when domains bind to
- * shared resources (setup eventchannels) and a domain is allowed
- * to setup sharing with another domain if and only if both domains
- * share at least on common type.
- *
- */
-
-#include <xen/lib.h>
-#include <asm/types.h>
-#include <asm/current.h>
-#include <asm/atomic.h>
-#include <xsm/acm/acm_hooks.h>
-#include <xsm/acm/acm_endian.h>
-#include <xsm/acm/acm_core.h>
-
-ssidref_t dom0_ste_ssidref = 0x0001;
-
-/* local cache structures for STE policy */
-struct ste_binary_policy ste_bin_pol;
-
-static inline int have_common_type (ssidref_t ref1, ssidref_t ref2)
-{
- int i;
-
- if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
- ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
- {
- for( i = 0; i< ste_bin_pol.max_types; i++ )
- if ( ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
- ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
- {
- printkd("%s: common type #%02x.\n", __func__, i);
- return 1;
- }
- }
- return 0;
-}
-
-static inline int is_superset(ssidref_t ref1, ssidref_t ref2)
-{
- int i;
-
- if ( ref1 >= 0 && ref1 < ste_bin_pol.max_ssidrefs &&
- ref2 >= 0 && ref2 < ste_bin_pol.max_ssidrefs )
- {
- for( i = 0; i< ste_bin_pol.max_types; i++ )
- if (!ste_bin_pol.ssidrefs[ref1 * ste_bin_pol.max_types + i] &&
- ste_bin_pol.ssidrefs[ref2 * ste_bin_pol.max_types + i])
- {
- return 0;
- }
- } else {
- return 0;
- }
- return 1;
-}
-
-
-/* Helper function: return = (subj and obj share a common type) */
-static int share_common_type(struct domain *subj, struct domain *obj)
-{
- ssidref_t ref_s, ref_o;
- int ret;
-
- if ( (subj == NULL) || (obj == NULL) ||
- (subj->ssid == NULL) || (obj->ssid == NULL) )
- return 0;
-
- read_lock(&acm_bin_pol_rwlock);
-
- /* lookup the policy-local ssids */
- ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
- ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
- /* check whether subj and obj share a common ste type */
- ret = have_common_type(ref_s, ref_o);
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return ret;
-}
-
-/*
- * Initializing STE policy (will be filled by policy partition
- * using setpolicy command)
- */
-int acm_init_ste_policy(void)
-{
- /* minimal startup policy; policy write-locked already */
- ste_bin_pol.max_types = 2;
- ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref;
- ste_bin_pol.ssidrefs =
- (domaintype_t *)xmalloc_array(domaintype_t,
- ste_bin_pol.max_types *
- ste_bin_pol.max_ssidrefs);
-
- if (ste_bin_pol.ssidrefs == NULL)
- return ACM_INIT_SSID_ERROR;
-
- memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) *
- ste_bin_pol.max_types *
- ste_bin_pol.max_ssidrefs);
-
- /* initialize state so that dom0 can start up and communicate with itself */
- ste_bin_pol.ssidrefs[ste_bin_pol.max_types - 1 ] = 1;
- ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1;
- ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref + 1] = 1;
-
- /* init stats */
- atomic_set(&(ste_bin_pol.ec_eval_count), 0);
- atomic_set(&(ste_bin_pol.ec_denied_count), 0);
- atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
- atomic_set(&(ste_bin_pol.gt_eval_count), 0);
- atomic_set(&(ste_bin_pol.gt_denied_count), 0);
- atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
-
- return ACM_OK;
-}
-
-
-/* ste initialization function hooks */
-static int
-ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
-{
- int i;
- struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
-
- if ( ste_ssidp == NULL )
- return ACM_INIT_SSID_ERROR;
-
- /* get policy-local ssid reference */
- ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- ssidref);
-
- if ( (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) )
- {
- printkd("%s: ERROR ste_ssidref (%x) undefined or unset (0).\n",
- __func__, ste_ssidp->ste_ssidref);
- xfree(ste_ssidp);
- return ACM_INIT_SSID_ERROR;
- }
- /* clean ste cache */
- for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- ste_ssidp->ste_cache[i].valid = ACM_STE_free;
-
- (*ste_ssid) = ste_ssidp;
- printkd("%s: determined ste_ssidref to %x.\n",
- __func__, ste_ssidp->ste_ssidref);
-
- return ACM_OK;
-}
-
-
-static void
-ste_free_domain_ssid(void *ste_ssid)
-{
- xfree(ste_ssid);
- return;
-}
-
-/* dump type enforcement cache; policy read-locked already */
-static int
-ste_dump_policy(u8 *buf, u32 buf_size) {
- struct acm_ste_policy_buffer *ste_buf =
- (struct acm_ste_policy_buffer *)buf;
- int ret = 0;
-
- if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
- return -EINVAL;
-
- ste_buf->ste_max_types = cpu_to_be32(ste_bin_pol.max_types);
- ste_buf->ste_max_ssidrefs = cpu_to_be32(ste_bin_pol.max_ssidrefs);
- ste_buf->policy_code = cpu_to_be32(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
- ste_buf->ste_ssid_offset =
- cpu_to_be32(sizeof(struct acm_ste_policy_buffer));
- ret = be32_to_cpu(ste_buf->ste_ssid_offset) +
- sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
-
- ret = (ret + 7) & ~7;
-
- if (buf_size < ret)
- return -EINVAL;
-
- /* now copy buffer over */
- arrcpy(buf + be32_to_cpu(ste_buf->ste_ssid_offset),
- ste_bin_pol.ssidrefs,
- sizeof(domaintype_t),
- ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
-
- return ret;
-}
-
-/*
- * ste_init_state is called when a policy is changed to detect violations
- * (return != 0). from a security point of view, we simulate that all
- * running domains are re-started and all sharing decisions are replayed
- * to detect violations or current sharing behavior (right now:
- * event_channels, future: also grant_tables)
- */
-static int
-ste_init_state(struct acm_sized_buffer *errors)
-{
- int violation = 1;
- struct ste_ssid *ste_ssid, *ste_rssid;
- ssidref_t ste_ssidref, ste_rssidref;
- struct domain *d, *rdom;
- domid_t rdomid;
- struct active_grant_entry *act;
- int port, i;
-
- rcu_read_lock(&domlist_read_lock);
- read_lock(&ssid_list_rwlock);
-
- /* go through all domains and adjust policy as if this domain was
- started now */
-
- for_each_domain ( d )
- {
- struct evtchn *ports;
- unsigned int bucket;
-
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)d->ssid);
- ste_ssidref = ste_ssid->ste_ssidref;
- traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
- __func__, d->domain_id, ste_ssidref);
- /* a) check for event channel conflicts */
- for ( bucket = 0; bucket < NR_EVTCHN_BUCKETS; bucket++ )
- {
- spin_lock(&d->event_lock);
- ports = d->evtchn[bucket];
- if ( ports == NULL)
- {
- spin_unlock(&d->event_lock);
- break;
- }
-
- for ( port = 0; port < EVTCHNS_PER_BUCKET; port++ )
- {
- if ( ports[port].state == ECS_INTERDOMAIN )
- {
- rdom = ports[port].u.interdomain.remote_dom;
- rdomid = rdom->domain_id;
- } else {
- continue; /* port unused */
- }
-
- /* rdom now has remote domain */
- ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(rdom->ssid));
- ste_rssidref = ste_rssid->ste_ssidref;
- traceprintk("%s: eventch: domain %x (ssidref %x) --> "
- "domain %x (rssidref %x) used (port %x).\n",
- __func__, d->domain_id, ste_ssidref,
- rdom->domain_id, ste_rssidref, port);
- /* check whether on subj->ssid, obj->ssid share a common type*/
- if ( ! have_common_type(ste_ssidref, ste_rssidref) )
- {
- printkd("%s: Policy violation in event channel domain "
- "%x -> domain %x.\n",
- __func__, d->domain_id, rdomid);
- spin_unlock(&d->event_lock);
-
- acm_array_append_tuple(errors,
- ACM_EVTCHN_SHARING_VIOLATION,
- d->domain_id << 16 | rdomid);
- goto out;
- }
- }
- spin_unlock(&d->event_lock);
- }
-
-
- /* b) check for grant table conflicts on shared pages */
- spin_lock(&d->grant_table->lock);
- for ( i = 0; i < nr_active_grant_frames(d->grant_table); i++ )
- {
-#define APP (PAGE_SIZE / sizeof(struct active_grant_entry))
- act = &d->grant_table->active[i/APP][i%APP];
- if ( act->pin != 0 ) {
- printkd("%s: grant dom (%hu) SHARED (%d) pin (%d) "
- "dom:(%hu) frame:(%lx)\n",
- __func__, d->domain_id, i, act->pin,
- act->domid, (unsigned long)act->frame);
- rdomid = act->domid;
- if ( (rdom = rcu_lock_domain_by_id(rdomid)) == NULL )
- {
- spin_unlock(&d->grant_table->lock);
- printkd("%s: domain not found ERROR!\n", __func__);
-
- acm_array_append_tuple(errors,
- ACM_DOMAIN_LOOKUP,
- rdomid);
- goto out;
- }
- /* rdom now has remote domain */
- ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(rdom->ssid));
- ste_rssidref = ste_rssid->ste_ssidref;
- rcu_unlock_domain(rdom);
- if ( ! have_common_type(ste_ssidref, ste_rssidref) )
- {
- spin_unlock(&d->grant_table->lock);
- printkd("%s: Policy violation in grant table "
- "sharing domain %x -> domain %x.\n",
- __func__, d->domain_id, rdomid);
-
- acm_array_append_tuple(errors,
- ACM_GNTTAB_SHARING_VIOLATION,
- d->domain_id << 16 | rdomid);
- goto out;
- }
- }
- }
- spin_unlock(&d->grant_table->lock);
- }
- violation = 0;
- out:
- read_unlock(&ssid_list_rwlock);
- rcu_read_unlock(&domlist_read_lock);
- return violation;
- /*
- returning "violation != 0" means that existing sharing between domains
- would not have been allowed if the new policy had been enforced before
- the sharing; for ste, this means that there are at least 2 domains
- that have established sharing through event-channels or grant-tables
- but these two domains don't have no longer a common type in their
- typesets referenced by their ssidrefs
- */
-}
-
-
-/*
- * Call ste_init_state with the current policy.
- */
-int
-do_ste_init_state_curr(struct acm_sized_buffer *errors)
-{
- return ste_init_state(errors);
-}
-
-
-/* set new policy; policy write-locked already */
-static int
-_ste_update_policy(u8 *buf, u32 buf_size, int test_only,
- struct acm_sized_buffer *errors)
-{
- int rc = -EFAULT;
- struct acm_ste_policy_buffer *ste_buf =
- (struct acm_ste_policy_buffer *)buf;
- void *ssidrefsbuf;
- struct ste_ssid *ste_ssid;
- struct acm_ssid_domain *rawssid;
- int i;
-
-
- /* 1. create and copy-in new ssidrefs buffer */
- ssidrefsbuf = xmalloc_array(u8,
- sizeof(domaintype_t) *
- ste_buf->ste_max_types *
- ste_buf->ste_max_ssidrefs);
- if ( ssidrefsbuf == NULL ) {
- return -ENOMEM;
- }
- if ( ste_buf->ste_ssid_offset +
- sizeof(domaintype_t) *
- ste_buf->ste_max_ssidrefs *
- ste_buf->ste_max_types > buf_size )
- goto error_free;
-
- arrcpy(ssidrefsbuf,
- buf + ste_buf->ste_ssid_offset,
- sizeof(domaintype_t),
- ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
-
-
- /*
- * 3. in test mode: re-calculate sharing decisions based on running
- * domains; this can fail if new policy is conflicting with sharing
- * of running domains
- * now: reject violating new policy; future: adjust sharing through
- * revoking sharing
- */
-
- if ( test_only ) {
- /* temporarily replace old policy with new one for the testing */
- struct ste_binary_policy orig_ste_bin_pol = ste_bin_pol;
- ste_bin_pol.max_types = ste_buf->ste_max_types;
- ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
- ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
-
- if ( ste_init_state(errors) )
- {
- /* new policy conflicts with sharing of running domains */
- printk("%s: New policy conflicts with running domains. "
- "Policy load aborted.\n", __func__);
- } else {
- rc = ACM_OK;
- }
- /* revert changes, no matter whether testing was successful or not */
- ste_bin_pol = orig_ste_bin_pol;
- goto error_free;
- }
-
- /* 3. replace old policy (activate new policy) */
- ste_bin_pol.max_types = ste_buf->ste_max_types;
- ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
- xfree(ste_bin_pol.ssidrefs);
- ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
-
- /* clear all ste caches */
- read_lock(&ssid_list_rwlock);
-
- for_each_acmssid( rawssid )
- {
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
- for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- ste_ssid->ste_cache[i].valid = ACM_STE_free;
- }
-
- read_unlock(&ssid_list_rwlock);
-
- return ACM_OK;
-
- error_free:
- if ( !test_only )
- printk("%s: ERROR setting policy.\n", __func__);
- xfree(ssidrefsbuf);
- return rc;
-}
-
-static int
-ste_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
- struct acm_sized_buffer *errors)
-{
- struct acm_ste_policy_buffer *ste_buf =
- (struct acm_ste_policy_buffer *)buf;
-
- if ( buf_size < sizeof(struct acm_ste_policy_buffer) )
- return -EINVAL;
-
- /* Convert endianess of policy */
- ste_buf->policy_code = be32_to_cpu(ste_buf->policy_code);
- ste_buf->policy_version = be32_to_cpu(ste_buf->policy_version);
- ste_buf->ste_max_types = be32_to_cpu(ste_buf->ste_max_types);
- ste_buf->ste_max_ssidrefs = be32_to_cpu(ste_buf->ste_max_ssidrefs);
- ste_buf->ste_ssid_offset = be32_to_cpu(ste_buf->ste_ssid_offset);
-
- /* policy type and version checks */
- if ( (ste_buf->policy_code != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ||
- (ste_buf->policy_version != ACM_STE_VERSION) )
- return -EINVAL;
-
- /* during boot dom0_chwall_ssidref is set */
- if ( is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs) )
- return -EINVAL;
-
- return _ste_update_policy(buf, buf_size, 1, errors);
-}
-
-static int
-ste_set_policy(u8 *buf, u32 buf_size)
-{
- return _ste_update_policy(buf, buf_size, 0, NULL);
-}
-
-static int
-ste_dump_stats(u8 *buf, u16 buf_len)
-{
- struct acm_ste_stats_buffer stats;
-
- /* now send the hook counts to user space */
- stats.ec_eval_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.ec_eval_count));
- stats.gt_eval_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.gt_eval_count));
- stats.ec_denied_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.ec_denied_count));
- stats.gt_denied_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.gt_denied_count));
- stats.ec_cachehit_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.ec_cachehit_count));
- stats.gt_cachehit_count =
- cpu_to_be32(atomic_read(&ste_bin_pol.gt_cachehit_count));
-
- if ( buf_len < sizeof(struct acm_ste_stats_buffer) )
- return -ENOMEM;
-
- memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
-
- return sizeof(struct acm_ste_stats_buffer);
-}
-
-static int
-ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
-{
- int i;
-
- /* fill in buffer */
- if ( ste_bin_pol.max_types > len )
- return -EFAULT;
-
- if ( ssidref >= ste_bin_pol.max_ssidrefs )
- return -EFAULT;
-
- /* read types for chwall ssidref */
- for( i = 0; i< ste_bin_pol.max_types; i++ )
- {
- if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
- buf[i] = 1;
- else
- buf[i] = 0;
- }
- return ste_bin_pol.max_types;
-}
-
-/* we need to go through this before calling the hooks,
- * returns 1 == cache hit */
-static int inline
-check_cache(struct domain *dom, domid_t rdom)
-{
- struct ste_ssid *ste_ssid;
- int i;
-
- printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
-
- if (dom->ssid == NULL)
- return 0;
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(dom->ssid));
-
- for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- {
- if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
- (ste_ssid->ste_cache[i].id == rdom) )
- {
- printkd("cache hit (entry %x, id= %x!\n",
- i,
- ste_ssid->ste_cache[i].id);
- return 1;
- }
- }
- return 0;
-}
-
-
-/* we only get here if there is NO entry yet; no duplication check! */
-static void inline
-cache_result(struct domain *subj, struct domain *obj) {
- struct ste_ssid *ste_ssid;
- int i;
-
- printkd("caching from doms: %x --> %x.\n",
- subj->domain_id, obj->domain_id);
-
- if ( subj->ssid == NULL )
- return;
-
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
- (struct acm_ssid_domain *)(subj)->ssid);
-
- for( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- if ( ste_ssid->ste_cache[i].valid == ACM_STE_free )
- break;
- if ( i < ACM_TE_CACHE_SIZE )
- {
- ste_ssid->ste_cache[i].valid = ACM_STE_valid;
- ste_ssid->ste_cache[i].id = obj->domain_id;
- } else
- printk ("Cache of dom %x is full!\n", subj->domain_id);
-}
-
-/* deletes entries for domain 'id' from all caches (re-use) */
-static void inline
-clean_id_from_cache(domid_t id)
-{
- struct ste_ssid *ste_ssid;
- int i;
- struct acm_ssid_domain *rawssid;
-
- printkd("deleting cache for dom %x.\n", id);
-
- read_lock(&ssid_list_rwlock);
- /* look through caches of all domains */
-
- for_each_acmssid ( rawssid )
- {
- ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, rawssid);
-
- if ( !ste_ssid )
- {
- printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n",
- __func__);
- goto out;
- }
- for ( i = 0; i < ACM_TE_CACHE_SIZE; i++ )
- if ( (ste_ssid->ste_cache[i].valid == ACM_STE_valid) &&
- (ste_ssid->ste_cache[i].id == id) )
- ste_ssid->ste_cache[i].valid = ACM_STE_free;
- }
-
- out:
- read_unlock(&ssid_list_rwlock);
-}
-
-/***************************
- * Authorization functions
- **************************/
-static int
-ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
-{
- /* check for ssidref in range for policy */
- ssidref_t ste_ssidref;
-
- traceprintk("%s.\n", __func__);
-
- read_lock(&acm_bin_pol_rwlock);
-
- ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
-
- if ( ste_ssidref >= ste_bin_pol.max_ssidrefs )
- {
- printk("%s: ERROR ste_ssidref > max(%x).\n",
- __func__, ste_bin_pol.max_ssidrefs-1);
- read_unlock(&acm_bin_pol_rwlock);
- return ACM_ACCESS_DENIED;
- }
-
- read_unlock(&acm_bin_pol_rwlock);
-
- return ACM_ACCESS_PERMITTED;
-}
-
-static int
-ste_domain_create(void *subject_ssid, ssidref_t ssidref, domid_t domid)
-{
- return ste_pre_domain_create(subject_ssid, ssidref);
-}
-
-
-static void
-ste_domain_destroy(void *subject_ssid, struct domain *d)
-{
- /* clean all cache entries for destroyed domain (might be re-used) */
- clean_id_from_cache(d->domain_id);
-}
-
-/* -------- EVENTCHANNEL OPERATIONS -----------*/
-static int
-ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) {
- struct domain *subj, *obj;
- int ret;
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- (id1 == DOMID_SELF) ? current->domain->domain_id : id1,
- (id2 == DOMID_SELF) ? current->domain->domain_id : id2);
-
- if ( id1 == DOMID_SELF )
- id1 = current->domain->domain_id;
- if ( id2 == DOMID_SELF )
- id2 = current->domain->domain_id;
-
- subj = rcu_lock_domain_by_id(id1);
- obj = rcu_lock_domain_by_id(id2);
- if ( (subj == NULL) || (obj == NULL) )
- {
- ret = ACM_ACCESS_DENIED;
- goto out;
- }
- /* cache check late */
- if ( check_cache(subj, obj->domain_id) )
- {
- atomic_inc(&ste_bin_pol.ec_cachehit_count);
- ret = ACM_ACCESS_PERMITTED;
- goto out;
- }
- atomic_inc(&ste_bin_pol.ec_eval_count);
-
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.ec_denied_count);
- ret = ACM_ACCESS_DENIED;
- }
-
- out:
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- if ( subj != NULL )
- rcu_unlock_domain(subj);
- return ret;
-}
-
-static int
-ste_pre_eventchannel_interdomain(domid_t id)
-{
- struct domain *subj=NULL, *obj=NULL;
- int ret;
-
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- current->domain->domain_id,
- (id == DOMID_SELF) ? current->domain->domain_id : id);
-
- /* following is a bit longer but ensures that we
- * "put" only domains that we where "find"-ing
- */
- if ( id == DOMID_SELF )
- id = current->domain->domain_id;
-
- subj = current->domain;
- obj = rcu_lock_domain_by_id(id);
- if ( obj == NULL )
- {
- ret = ACM_ACCESS_DENIED;
- goto out;
- }
-
- /* cache check late, but evtchn is not on performance critical path */
- if ( check_cache(subj, obj->domain_id) )
- {
- atomic_inc(&ste_bin_pol.ec_cachehit_count);
- ret = ACM_ACCESS_PERMITTED;
- goto out;
- }
-
- atomic_inc(&ste_bin_pol.ec_eval_count);
-
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.ec_denied_count);
- ret = ACM_ACCESS_DENIED;
- }
-
- out:
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- return ret;
-}
-
-/* -------- SHARED MEMORY OPERATIONS -----------*/
-
-static int
-ste_pre_grant_map_ref (domid_t id)
-{
- struct domain *obj, *subj;
- int ret;
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- current->domain->domain_id, id);
-
- if ( check_cache(current->domain, id) )
- {
- atomic_inc(&ste_bin_pol.gt_cachehit_count);
- return ACM_ACCESS_PERMITTED;
- }
- atomic_inc(&ste_bin_pol.gt_eval_count);
- subj = current->domain;
- obj = rcu_lock_domain_by_id(id);
-
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.gt_denied_count);
- printkd("%s: ACCESS DENIED!\n", __func__);
- ret = ACM_ACCESS_DENIED;
- }
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- return ret;
-}
-
-
-/* since setting up grant tables involves some implicit information
- flow from the creating domain to the domain that is setup, we
- check types in addition to the general authorization */
-static int
-ste_pre_grant_setup (domid_t id)
-{
- struct domain *obj, *subj;
- int ret;
- traceprintk("%s: dom%x-->dom%x.\n", __func__,
- current->domain->domain_id, id);
-
- if ( check_cache(current->domain, id) )
- {
- atomic_inc(&ste_bin_pol.gt_cachehit_count);
- return ACM_ACCESS_PERMITTED;
- }
- atomic_inc(&ste_bin_pol.gt_eval_count);
- subj = current->domain;
- obj = rcu_lock_domain_by_id(id);
-
- /* a) check authorization (eventually use specific capabilities) */
- if ( obj && !IS_PRIV_FOR(current->domain, obj) )
- {
- printk("%s: Grant table management authorization denied ERROR!\n",
- __func__);
- rcu_unlock_domain(obj);
- return ACM_ACCESS_DENIED;
- }
-
- /* b) check types */
- if ( share_common_type(subj, obj) )
- {
- cache_result(subj, obj);
- ret = ACM_ACCESS_PERMITTED;
- }
- else
- {
- atomic_inc(&ste_bin_pol.gt_denied_count);
- ret = ACM_ACCESS_DENIED;
- }
- if ( obj != NULL )
- rcu_unlock_domain(obj);
- return ret;
-}
-
-/* -------- DOMAIN-Requested Decision hooks -----------*/
-
-static int
-ste_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
-{
- int hct = have_common_type(
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
- return (hct ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
-}
-
-static int
-ste_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
-{
- int iss = is_superset(
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref1),
- GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref2));
- return (iss ? ACM_ACCESS_PERMITTED : ACM_ACCESS_DENIED);
-}
-
-static int
-ste_is_default_policy(void)
-{
- const static domaintype_t def_policy[4] = { 0x0, 0x1, 0x1, 0x1};
- return ((ste_bin_pol.max_types == 2) &&
- (ste_bin_pol.max_ssidrefs == 2) &&
- (memcmp(ste_bin_pol.ssidrefs,
- def_policy,
- sizeof(def_policy)) == 0));
-}
-
-/* now define the hook structure similarly to LSM */
-struct acm_operations acm_simple_type_enforcement_ops = {
-
- /* policy management services */
- .init_domain_ssid = ste_init_domain_ssid,
- .free_domain_ssid = ste_free_domain_ssid,
- .dump_binary_policy = ste_dump_policy,
- .test_binary_policy = ste_test_policy,
- .set_binary_policy = ste_set_policy,
- .dump_statistics = ste_dump_stats,
- .dump_ssid_types = ste_dump_ssid_types,
-
- /* domain management control hooks */
- .domain_create = ste_domain_create,
- .domain_destroy = ste_domain_destroy,
-
- /* event channel control hooks */
- .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
- .fail_eventchannel_unbound = NULL,
- .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
- .fail_eventchannel_interdomain = NULL,
-
- /* grant table control hooks */
- .pre_grant_map_ref = ste_pre_grant_map_ref,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = ste_pre_grant_setup,
- .fail_grant_setup = NULL,
- /* generic domain-requested decision hooks */
- .sharing = ste_sharing,
- .authorization = ste_authorization,
- .conflictset = NULL,
-
- .is_default_policy = ste_is_default_policy,
-};
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/xsm/acm/acm_xsm_hooks.c b/xen/xsm/acm/acm_xsm_hooks.c
deleted file mode 100644
index 6d3202b45f..0000000000
--- a/xen/xsm/acm/acm_xsm_hooks.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************
- * acm_xsm_hooks.c
- *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
- * Reiner Sailer <sailer@watson.ibm.com>
- *
- * Contributors:
- * Michael LeMay, <mdlemay@epoch.ncsc.mil>
- * George Coker, <gscoker@alpha.ncsc.mil>
- *
- * sHype hooks for XSM based on the original ACM hooks.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- *
- */
-
-#include <xsm/xsm.h>
-#include <xsm/acm/acm_hooks.h>
-#include <public/xsm/acm.h>
-
-static int acm_grant_mapref(
- struct domain *ld, struct domain *rd, uint32_t flags)
-{
- domid_t id = rd->domain_id;
-
- return acm_pre_grant_map_ref(id);
-}
-
-static int acm_evtchn_unbound(
- struct domain *d1, struct evtchn *chn1, domid_t id2)
-{
- domid_t id1 = d1->domain_id;
-
- return acm_pre_eventchannel_unbound(id1, id2);
-}
-
-static int acm_evtchn_interdomain(
- struct domain *d1, struct evtchn *chn1,
- struct domain *d2, struct evtchn *chn2)
-{
- domid_t id2 = d2->domain_id;
-
- return acm_pre_eventchannel_interdomain(id2);
-}
-
-static void acm_security_domaininfo(
- struct domain *d, struct xen_domctl_getdomaininfo *info)
-{
- if ( d->ssid != NULL )
- info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
- else
- info->ssidref = ACM_DEFAULT_SSID;
-}
-
-extern long do_acm_op(XEN_GUEST_HANDLE(xsm_op_t) arg);
-
-struct xsm_operations acm_xsm_ops = {
- .domain_create = acm_domain_create,
- .free_security_domain = acm_domain_destroy,
-
- .grant_mapref = acm_grant_mapref,
-
- .evtchn_unbound = acm_evtchn_unbound,
- .evtchn_interdomain = acm_evtchn_interdomain,
-
- .security_domaininfo = acm_security_domaininfo,
-
- .__do_xsm_op = do_acm_op,
-};
diff --git a/xen/xsm/xsm_policy.c b/xen/xsm/xsm_policy.c
index dcab94d580..c5b334e7e9 100644
--- a/xen/xsm/xsm_policy.c
+++ b/xen/xsm/xsm_policy.c
@@ -15,7 +15,6 @@
*
*
* This file contains the XSM policy init functions for Xen.
- * This file is based on the ACM functions of the same name.
*
*/