diff -uprN xeno-unstable.bk_orig/xen/acm/acm_chinesewall_hooks.c xeno-unstable.bk-shype/xen/acm/acm_chinesewall_hooks.c --- xeno-unstable.bk_orig/xen/acm/acm_chinesewall_hooks.c 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/acm/acm_chinesewall_hooks.c 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,503 @@ +/**************************************************************** + * acm_chinesewall_hooks.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * Contributions: + * Stefan Berger + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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; + 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; + /* + * depending on wheter chwall is primary or secondary, get the respective + * part of the global ssidref (same way we'll get the partial ssid pointer) + */ + 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) > max(%x).\n", + __func__, chwall_ssidp->chwall_ssidref, chwall_bin_pol.max_ssidrefs-1); + 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) +{ + traceprintk("%s.\n", __func__); + if (chwall_ssid != NULL) + xfree(chwall_ssid); + return; +} + + +/* dump chinese wall cache; policy read-locked already */ +static int +chwall_dump_policy(u8 *buf, u16 buf_size) { + struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf; + int ret = 0; + + chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types); + chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs); + chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY); + chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer)); + chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets); + chwall_buf->chwall_conflict_sets_offset = + htons( + ntohs(chwall_buf->chwall_ssid_offset) + + sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs * + chwall_bin_pol.max_types); + + chwall_buf->chwall_running_types_offset = + htons( + ntohs(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 = + htons( + ntohs(chwall_buf->chwall_running_types_offset) + + sizeof(domaintype_t) * chwall_bin_pol.max_types); + + ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) + + sizeof(domaintype_t) * chwall_bin_pol.max_types; + + /* now copy buffers over */ + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)), + chwall_bin_pol.ssidrefs, + chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types); + + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)), + chwall_bin_pol.conflict_sets, + chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types); + + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)), + chwall_bin_pol.running_types, + chwall_bin_pol.max_types); + + arrcpy16((u16 *)(buf + ntohs(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) +{ + int violation = 0, i, j; + struct chwall_ssid *chwall_ssid; + ssidref_t chwall_ssidref; + struct domain **pd; + + write_lock(&domlist_lock); + /* go through all domains and adjust policy as if this domain was started now */ + pd = &domain_list; + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { + chwall_ssid = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)(*pd)->ssid); + chwall_ssidref = chwall_ssid->chwall_ssidref; + traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n", + __func__, (*pd)->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; + goto out; + } + /* set violation and break out of the loop */ + /* c) adapt conflict aggregate set for this domain (notice conflicts) */ + for (i=0; ichwall_max_conflictsets; i++) { + int common = 0; + /* check if conflict_set_i and ssidref have common types */ + for (j=0; jchwall_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; jchwall_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: + write_unlock(&domlist_lock); + 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 */ +} + +static int +chwall_set_policy(u8 *buf, u16 buf_size) +{ + /* 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; + + /* rewrite the policy due to endianess */ + chwall_buf->policy_code = ntohs(chwall_buf->policy_code); + chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types); + chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs); + chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets); + chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset); + chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset); + chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset); + chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset); + + /* 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)) { + printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__); + goto error_free; /* new policy conflicts with running domains */ + } + /* 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; + if (chwall_bin_pol.ssidrefs != NULL) + xfree(chwall_bin_pol.ssidrefs); + if (chwall_bin_pol.conflict_aggregate_set != NULL) + xfree(chwall_bin_pol.conflict_aggregate_set); + if (chwall_bin_pol.running_types != NULL) + xfree(chwall_bin_pol.running_types); + if (chwall_bin_pol.conflict_sets != NULL) + 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: + printk("%s: ERROR setting policy.\n", __func__); + if (ssids != NULL) xfree(ssids); + if (conflict_sets != NULL) xfree(conflict_sets); + if (running_types != NULL) xfree(running_types); + if (conflict_aggregate_set != NULL) xfree(conflict_aggregate_set); + return -EFAULT; +} + +static int +chwall_dump_stats(u8 *buf, u16 len) +{ + /* no stats for Chinese Wall Policy */ + return 0; +} + +/*************************** + * Authorization functions + ***************************/ + + +/* -------- DOMAIN OPERATION HOOKS -----------*/ + +static int +chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref) +{ + ssidref_t chwall_ssidref; + int i,j; + traceprintk("%s.\n", __func__); + + read_lock(&acm_bin_pol_rwlock); + chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); + if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) { + printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", __func__); + read_unlock(&acm_bin_pol_rwlock); + return ACM_ACCESS_DENIED; /* catching and indicating config error */ + } + if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) { + printk("%s: ERROR chwall_ssidref > max(%x).\n", + __func__, chwall_bin_pol.max_ssidrefs-1); + read_unlock(&acm_bin_pol_rwlock); + 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); + read_unlock(&acm_bin_pol_rwlock); + 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; ichwall_ssidref; + + traceprintk("%s.\n", __func__); + + 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +/* debug: + * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE; + * define/undefine this constant to receive / suppress any + * security hook debug output of sHype + * + * include/public/acm.h defines a constant ACM_DEBUG + * define/undefine this constant to receive non-hook-related + * debug output. + */ + +/* function prototypes */ +void acm_init_chwall_policy(void); +void acm_init_ste_policy(void); + +extern struct acm_operations acm_chinesewall_ops, + acm_simple_type_enforcement_ops, acm_null_ops; + +/* global 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 */ +rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED; + +/* until we have endian support in Xen, we discover it at runtime */ +u8 little_endian = 1; +void acm_set_endian(void) +{ + u32 test = 1; + if (*((u8 *)&test) == 1) { + printk("ACM module running in LITTLE ENDIAN.\n"); + little_endian = 1; + } else { + printk("ACM module running in BIG ENDIAN.\n"); + little_endian = 0; + } +} + +/* initialize global security policy for Xen; policy write-locked already */ +static void +acm_init_binary_policy(void *primary, void *secondary) +{ + acm_bin_pol.primary_policy_code = 0; + acm_bin_pol.secondary_policy_code = 0; + acm_bin_pol.primary_binary_policy = primary; + acm_bin_pol.secondary_binary_policy = secondary; +} + +int +acm_init(void) +{ + int ret = -EINVAL; + + acm_set_endian(); + write_lock(&acm_bin_pol_rwlock); + + if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) { + acm_init_binary_policy(NULL, NULL); + acm_init_chwall_policy(); + acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; + acm_primary_ops = &acm_chinesewall_ops; + acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; + acm_secondary_ops = &acm_null_ops; + ret = ACM_OK; + } else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) { + acm_init_binary_policy(NULL, NULL); + acm_init_ste_policy(); + acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; + acm_primary_ops = &acm_simple_type_enforcement_ops; + acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; + acm_secondary_ops = &acm_null_ops; + ret = ACM_OK; + } else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) { + acm_init_binary_policy(NULL, NULL); + acm_init_chwall_policy(); + acm_init_ste_policy(); + acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; + acm_primary_ops = &acm_chinesewall_ops; + acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; + acm_secondary_ops = &acm_simple_type_enforcement_ops; + ret = ACM_OK; + } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) { + acm_init_binary_policy(NULL, NULL); + acm_bin_pol.primary_policy_code = ACM_NULL_POLICY; + acm_primary_ops = &acm_null_ops; + acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; + acm_secondary_ops = &acm_null_ops; + ret = ACM_OK; + } + write_unlock(&acm_bin_pol_rwlock); + + if (ret != ACM_OK) + return -EINVAL; + printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__, + ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code)); + return ACM_OK; +} + + +int +acm_init_domain_ssid(domid_t id, ssidref_t ssidref) +{ + struct acm_ssid_domain *ssid; + struct domain *subj = find_domain_by_id(id); + int ret1, ret2; + + if (subj == NULL) { + printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id); + return ACM_NULL_POINTER_ERROR; + } + if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL) + return ACM_INIT_SSID_ERROR; + + ssid->datatype = DOMAIN; + ssid->subject = subj; + ssid->domainid = subj->domain_id; + ssid->primary_ssid = NULL; + ssid->secondary_ssid = NULL; + + if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY) + ssid->ssidref = ssidref; + else + ssid->ssidref = ACM_DEFAULT_SSID; + + subj->ssid = ssid; + /* now fill in primary and secondary parts; we only get here through hooks */ + if (acm_primary_ops->init_domain_ssid != NULL) + ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref); + else + ret1 = ACM_OK; + + if (acm_secondary_ops->init_domain_ssid != NULL) + ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref); + else + ret2 = ACM_OK; + + if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) { + printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n", + __func__, subj->domain_id); + acm_free_domain_ssid(ssid); + put_domain(subj); + return ACM_INIT_SSID_ERROR; + } + printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref); + put_domain(subj); + return ACM_OK; +} + + +int +acm_free_domain_ssid(struct acm_ssid_domain *ssid) +{ + domid_t id; + + /* domain is already gone, just ssid is left */ + if (ssid == NULL) { + printk("%s: ACM_NULL_POINTER ERROR.\n", __func__); + return ACM_NULL_POINTER_ERROR; + } + id = ssid->domainid; + ssid->subject = NULL; + + if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */ + acm_primary_ops->free_domain_ssid(ssid->primary_ssid); + ssid->primary_ssid = NULL; + if (acm_secondary_ops->free_domain_ssid != NULL) + acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid); + ssid->secondary_ssid = NULL; + xfree(ssid); + printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id); + return ACM_OK; +} diff -uprN xeno-unstable.bk_orig/xen/acm/acm_null_hooks.c xeno-unstable.bk-shype/xen/acm/acm_null_hooks.c --- xeno-unstable.bk_orig/xen/acm/acm_null_hooks.c 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/acm/acm_null_hooks.c 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,76 @@ +/**************************************************************** + * acm_null_hooks.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * 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 + +static int +null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref) +{ + return ACM_OK; +} + + +static void +null_free_domain_ssid(void *chwall_ssid) +{ + return; +} + + +static int +null_dump_binary_policy(u8 *buf, u16 buf_size) +{ + return 0; +} + + + +static int +null_set_binary_policy(u8 *buf, u16 buf_size) +{ + return -1; +} + + +static int +null_dump_stats(u8 *buf, u16 buf_size) +{ + /* no stats for NULL policy */ + 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, + .set_binary_policy = null_set_binary_policy, + .dump_statistics = null_dump_stats, + /* domain management control hooks */ + .pre_domain_create = NULL, + .post_domain_create = NULL, + .fail_domain_create = NULL, + .post_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 + +}; diff -uprN xeno-unstable.bk_orig/xen/acm/acm_policy.c xeno-unstable.bk-shype/xen/acm/acm_policy.c --- xeno-unstable.bk_orig/xen/acm/acm_policy.c 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/acm/acm_policy.c 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,197 @@ +/**************************************************************** + * acm_policy.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * Contributions: + * Stefan Berger + * support for network-byte-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 access control policy management for Xen. + * This interface allows policy tools in authorized + * domains to interact with the Xen access control module + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +acm_set_policy(void *buf, u16 buf_size, u16 policy) +{ + u8 *policy_buffer = NULL; + struct acm_policy_buffer *pol; + + if (policy != ACM_USE_SECURITY_POLICY) { + printk("%s: Loading incompatible policy (running: %s).\n", __func__, + ACM_POLICY_NAME(ACM_USE_SECURITY_POLICY)); + return -EFAULT; + } + /* now check correct buffer sizes for policy combinations */ + if (policy == ACM_NULL_POLICY) { + printkd("%s: NULL Policy, no policy needed.\n", __func__); + goto out; + } + if (buf_size < sizeof(struct acm_policy_buffer)) + return -EFAULT; + /* 1. copy buffer from domain */ + if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) + goto error_free; + if (copy_from_user(policy_buffer, buf, buf_size)) { + printk("%s: Error copying!\n",__func__); + goto error_free; + } + /* 2. some sanity checking */ + pol = (struct acm_policy_buffer *)policy_buffer; + + if ((ntohl(pol->magic) != ACM_MAGIC) || + (ntohs(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) || + (ntohs(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) { + printkd("%s: Wrong policy magics!\n", __func__); + goto error_free; + } + if (buf_size != ntohl(pol->len)) { + printk("%s: ERROR in buf size.\n", __func__); + goto error_free; + } + + /* get bin_policy lock and rewrite policy (release old one) */ + write_lock(&acm_bin_pol_rwlock); + + /* 3. now get/set primary policy data */ + if (acm_primary_ops->set_binary_policy(buf + ntohs(pol->primary_buffer_offset), + ntohs(pol->secondary_buffer_offset) - + ntohs(pol->primary_buffer_offset))) { + goto error_lock_free; + } + /* 4. now get/set secondary policy data */ + if (acm_secondary_ops->set_binary_policy(buf + ntohs(pol->secondary_buffer_offset), + ntohl(pol->len) - + ntohs(pol->secondary_buffer_offset))) { + goto error_lock_free; + } + write_unlock(&acm_bin_pol_rwlock); + out: + printk("%s: Done .\n", __func__); + if (policy_buffer != NULL) + xfree(policy_buffer); + return ACM_OK; + + error_lock_free: + write_unlock(&acm_bin_pol_rwlock); + error_free: + printk("%s: Error setting policy.\n", __func__); + if (policy_buffer != NULL) + xfree(policy_buffer); + return -ENOMEM; +} + +int +acm_get_policy(void *buf, u16 buf_size) +{ + u8 *policy_buffer; + int ret; + struct acm_policy_buffer *bin_pol; + + if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) + return -ENOMEM; + + read_lock(&acm_bin_pol_rwlock); + /* future: read policy from file and set it */ + bin_pol = (struct acm_policy_buffer *)policy_buffer; + bin_pol->magic = htonl(ACM_MAGIC); + bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION); + bin_pol->primary_policy_code = htons(acm_bin_pol.primary_policy_code); + bin_pol->secondary_policy_code = htons(acm_bin_pol.secondary_policy_code); + + bin_pol->len = htonl(sizeof(struct acm_policy_buffer)); + bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len)); + bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len)); + + ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohs(bin_pol->primary_buffer_offset), + buf_size - ntohs(bin_pol->primary_buffer_offset)); + if (ret < 0) { + printk("%s: ERROR creating chwallpolicy buffer.\n", __func__); + read_unlock(&acm_bin_pol_rwlock); + return -1; + } + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); + bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len)); + + ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohs(bin_pol->secondary_buffer_offset), + buf_size - ntohs(bin_pol->secondary_buffer_offset)); + if (ret < 0) { + printk("%s: ERROR creating chwallpolicy buffer.\n", __func__); + read_unlock(&acm_bin_pol_rwlock); + return -1; + } + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); + read_unlock(&acm_bin_pol_rwlock); + if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len))) + return -EFAULT; + xfree(policy_buffer); + return ACM_OK; +} + +int +acm_dump_statistics(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 = htonl(ACM_MAGIC); + acm_stats.policyversion = htonl(POLICY_INTERFACE_VERSION); + acm_stats.primary_policy_code = htons(acm_bin_pol.primary_policy_code); + acm_stats.secondary_policy_code = htons(acm_bin_pol.secondary_policy_code); + acm_stats.primary_stats_offset = htons(sizeof(struct acm_stats_buffer)); + acm_stats.secondary_stats_offset = htons(sizeof(struct acm_stats_buffer) + len1); + acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2); + memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer)); + + if (copy_to_user(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; +} + +/*eof*/ diff -uprN xeno-unstable.bk_orig/xen/acm/acm_simple_type_enforcement_hooks.c xeno-unstable.bk-shype/xen/acm/acm_simple_type_enforcement_hooks.c --- xeno-unstable.bk_orig/xen/acm/acm_simple_type_enforcement_hooks.c 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/acm/acm_simple_type_enforcement_hooks.c 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,638 @@ +/**************************************************************** + * acm_simple_type_enforcement_hooks.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * Contributors: + * Stefan Berger + * 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 +#include +#include +#include +#include +#include + +/* local cache structures for chinese wall policy */ +struct ste_binary_policy ste_bin_pol; + +static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) { + int i; + 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; +} + +/* 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 chinese wall policy (will be filled by policy partition + * using setpolicy command) + */ +int acm_init_ste_policy(void) +{ + /* minimal startup policy; policy write-locked already */ + ste_bin_pol.max_types = 1; + ste_bin_pol.max_ssidrefs = 1; + ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 1); + + if (ste_bin_pol.ssidrefs == NULL) + return ACM_INIT_SSID_ERROR; + + /* initialize state */ + ste_bin_pol.ssidrefs[0] = 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); + traceprintk("%s.\n", __func__); + + 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) > max(%x).\n", + __func__, ste_ssidp->ste_ssidref, ste_bin_pol.max_ssidrefs-1); + xfree(ste_ssidp); + return ACM_INIT_SSID_ERROR; + } + /* clean ste cache */ + for (i=0; iste_cache[i].valid = 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) +{ + traceprintk("%s.\n", __func__); + if (ste_ssid != NULL) + xfree(ste_ssid); + return; +} + +/* dump type enforcement cache; policy read-locked already */ +static int +ste_dump_policy(u8 *buf, u16 buf_size) { + struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf; + int ret = 0; + + ste_buf->ste_max_types = htons(ste_bin_pol.max_types); + ste_buf->ste_max_ssidrefs = htons(ste_bin_pol.max_ssidrefs); + ste_buf->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); + ste_buf->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer)); + ret = ntohs(ste_buf->ste_ssid_offset) + + sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types; + + /* now copy buffer over */ + arrcpy(buf + ntohs(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_ste_policy_buffer *ste_buf, domaintype_t *ssidrefs) +{ + int violation = 1; + struct ste_ssid *ste_ssid, *ste_rssid; + ssidref_t ste_ssidref, ste_rssidref; + struct domain **pd, *rdom; + domid_t rdomid; + grant_entry_t sha_copy; + int port, i; + + read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */ + /* go through all domains and adjust policy as if this domain was started now */ + pd = &domain_list; + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, + (struct acm_ssid_domain *)(*pd)->ssid); + ste_ssidref = ste_ssid->ste_ssidref; + traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n", + __func__, (*pd)->domain_id, ste_ssidref); + /* a) check for event channel conflicts */ + for (port=0; port < NR_EVTCHN_BUCKETS; port++) { + spin_lock(&(*pd)->evtchn_lock); + if ((*pd)->evtchn[port] == NULL) { + spin_unlock(&(*pd)->evtchn_lock); + continue; + } + if ((*pd)->evtchn[port]->state == ECS_INTERDOMAIN) { + rdom = (*pd)->evtchn[port]->u.interdomain.remote_dom; + rdomid = rdom->domain_id; + /* 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; + } else if ((*pd)->evtchn[port]->state == ECS_UNBOUND) { + rdomid = (*pd)->evtchn[port]->u.unbound.remote_domid; + if ((rdom = find_domain_by_id(rdomid)) == NULL) { + printk("%s: Error finding domain to id %x!\n", __func__, 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; + put_domain(rdom); + } else { + spin_unlock(&(*pd)->evtchn_lock); + continue; /* port unused */ + } + spin_unlock(&(*pd)->evtchn_lock); + + /* 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__, (*pd)->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__, (*pd)->domain_id, rdomid); + goto out; + } + } + /* b) check for grant table conflicts on shared pages */ + if ((*pd)->grant_table->shared == NULL) { + printkd("%s: Grant ... sharing for domain %x not setup!\n", __func__, (*pd)->domain_id); + continue; + } + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) { + sha_copy = (*pd)->grant_table->shared[i]; + if ( sha_copy.flags ) { + printkd("%s: grant dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n", + __func__, (*pd)->domain_id, i, sha_copy.flags, sha_copy.domid, + (unsigned long)sha_copy.frame); + rdomid = sha_copy.domid; + if ((rdom = find_domain_by_id(rdomid)) == NULL) { + printkd("%s: domain not found ERROR!\n", __func__); + 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; + put_domain(rdom); + if (!have_common_type(ste_ssidref, ste_rssidref)) { + printkd("%s: Policy violation in grant table sharing domain %x -> domain %x.\n", + __func__, (*pd)->domain_id, rdomid); + goto out; + } + } + } + } + violation = 0; + out: + read_unlock(&domlist_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 */ +} + +/* set new policy; policy write-locked already */ +static int +ste_set_policy(u8 *buf, u16 buf_size) +{ + struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf; + void *ssidrefsbuf; + struct ste_ssid *ste_ssid; + struct domain **pd; + int i; + + /* Convert endianess of policy */ + ste_buf->policy_code = ntohs(ste_buf->policy_code); + ste_buf->ste_max_types = ntohs(ste_buf->ste_max_types); + ste_buf->ste_max_ssidrefs = ntohs(ste_buf->ste_max_ssidrefs); + ste_buf->ste_ssid_offset = ntohs(ste_buf->ste_ssid_offset); + + /* 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); + + /* 2. now 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 (ste_init_state(ste_buf, (domaintype_t *)ssidrefsbuf)) { + printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__); + goto error_free; /* new policy conflicts with sharing of running domains */ + } + /* 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; + if (ste_bin_pol.ssidrefs) + xfree(ste_bin_pol.ssidrefs); + ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf; + + /* clear all ste caches */ + read_lock(&domlist_lock); + pd = &domain_list; + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, + (struct acm_ssid_domain *)(*pd)->ssid); + for (i=0; iste_cache[i].valid = FREE; + } + read_unlock(&domlist_lock); + return ACM_OK; + +error_free: + printk("%s: ERROR setting policy.\n", __func__); + if (ssidrefsbuf != NULL) xfree(ssidrefsbuf); + return -EFAULT; +} + +static int +ste_dump_stats(u8 *buf, u16 buf_len) +{ + struct acm_ste_stats_buffer stats; + +#ifdef ACM_DEBUG + int i; + struct ste_ssid *ste_ssid; + struct domain **pd; + + printk("ste: Decision caches:\n"); + /* go through all domains and adjust policy as if this domain was started now */ + read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */ + pd = &domain_list; + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { + printk("ste: Cache Domain %02x.\n", (*pd)->domain_id); + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, + (struct acm_ssid_domain *)(*pd)->ssid); + for (i=0; iste_cache[i].valid == VALID) ? + "VALID" : "FREE", + (ste_ssid->ste_cache[i].valid == VALID) ? + ste_ssid->ste_cache[i].id : 0xffffffff); + } + read_unlock(&domlist_lock); + /* init stats */ + printk("STE-Policy Security Hook Statistics:\n"); + printk("ste: event_channel eval_count = %x\n", atomic_read(&(ste_bin_pol.ec_eval_count))); + printk("ste: event_channel denied_count = %x\n", atomic_read(&(ste_bin_pol.ec_denied_count))); + printk("ste: event_channel cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.ec_cachehit_count))); + printk("ste:\n"); + printk("ste: grant_table eval_count = %x\n", atomic_read(&(ste_bin_pol.gt_eval_count))); + printk("ste: grant_table denied_count = %x\n", atomic_read(&(ste_bin_pol.gt_denied_count))); + printk("ste: grant_table cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.gt_cachehit_count))); +#endif + + if (buf_len < sizeof(struct acm_ste_stats_buffer)) + return -ENOMEM; + + /* now send the hook counts to user space */ + stats.ec_eval_count = htonl(atomic_read(&ste_bin_pol.ec_eval_count)); + stats.gt_eval_count = htonl(atomic_read(&ste_bin_pol.gt_eval_count)); + stats.ec_denied_count = htonl(atomic_read(&ste_bin_pol.ec_denied_count)); + stats.gt_denied_count = htonl(atomic_read(&ste_bin_pol.gt_denied_count)); + stats.ec_cachehit_count = htonl(atomic_read(&ste_bin_pol.ec_cachehit_count)); + stats.gt_cachehit_count = htonl(atomic_read(&ste_bin_pol.gt_cachehit_count)); + memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer)); + return sizeof(struct acm_ste_stats_buffer); +} + + +/* 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); + 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 == 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); + 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 == FREE) + break; + if (i< ACM_TE_CACHE_SIZE) { + ste_ssid->ste_cache[i].valid = 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 domain **pd; + + printkd("deleting cache for dom %x.\n", id); + + read_lock(&domlist_lock); /* look through caches of all domains */ + pd = &domain_list; + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, + (struct acm_ssid_domain *)(*pd)->ssid); + for (i=0; iste_cache[i].valid == VALID) && + (ste_ssid->ste_cache[i].id = id)) + ste_ssid->ste_cache[i].valid = FREE; + } + read_unlock(&domlist_lock); +} + +/*************************** + * 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 == ACM_DEFAULT_LOCAL_SSID) { + printk("%s: ERROR STE SSID is NOT SET but policy enforced.\n", __func__); + read_unlock(&acm_bin_pol_rwlock); + return ACM_ACCESS_DENIED; /* catching and indicating config error */ + } + 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 void +ste_post_domain_destroy(void *subject_ssid, domid_t id) +{ + /* clean all cache entries for destroyed domain (might be re-used) */ + clean_id_from_cache(id); +} + +/* -------- EVENTCHANNEL OPERATIONS -----------*/ +static int +ste_pre_eventchannel_unbound(domid_t id) { + struct domain *subj, *obj; + 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.ec_cachehit_count); + return ACM_ACCESS_PERMITTED; + } + atomic_inc(&ste_bin_pol.ec_eval_count); + subj = current->domain; + obj = find_domain_by_id(id); + + 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; + } + if (obj != NULL) + put_domain(obj); + return ret; +} + +static int +ste_pre_eventchannel_interdomain(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); + + /* following is a bit longer but ensures that we + * "put" only domains that we where "find"-ing + */ + if (id1 == DOMID_SELF) id1 = current->domain->domain_id; + if (id2 == DOMID_SELF) id2 = current->domain->domain_id; + + subj = find_domain_by_id(id1); + obj = find_domain_by_id(id2); + if ((subj == NULL) || (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) + put_domain(obj); + if (subj != NULL) + put_domain(subj); + 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 = find_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) + put_domain(obj); + return ret; +} + +/* since setting up grant tables involves some implicit information + flow from the creating domain to the domain that is setup, we + check types in addition to the general authorization */ +static int +ste_pre_grant_setup (domid_t id) { + struct domain *obj, *subj; + int ret; + traceprintk("%s: dom%x-->dom%x.\n", __func__, + current->domain->domain_id, id); + + if (check_cache(current->domain, id)) { + atomic_inc(&ste_bin_pol.gt_cachehit_count); + return ACM_ACCESS_PERMITTED; + } + atomic_inc(&ste_bin_pol.gt_eval_count); + /* a) check authorization (eventually use specific capabilities) */ + if (!IS_PRIV(current->domain)) { + printk("%s: Grant table management authorization denied ERROR!\n", __func__); + return ACM_ACCESS_DENIED; + } + /* b) check types */ + subj = current->domain; + obj = find_domain_by_id(id); + + if (share_common_type(subj, obj)) { + cache_result(subj, obj); + ret = ACM_ACCESS_PERMITTED; + } else { + atomic_inc(&ste_bin_pol.gt_denied_count); + ret = ACM_ACCESS_DENIED; + } + if (obj != NULL) + put_domain(obj); + return ret; +} + +/* 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, + .set_binary_policy = ste_set_policy, + .dump_statistics = ste_dump_stats, + /* domain management control hooks */ + .pre_domain_create = ste_pre_domain_create, + .post_domain_create = NULL, + .fail_domain_create = NULL, + .post_domain_destroy = ste_post_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, +}; diff -uprN xeno-unstable.bk_orig/xen/acm/Makefile xeno-unstable.bk-shype/xen/acm/Makefile --- xeno-unstable.bk_orig/xen/acm/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/acm/Makefile 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,15 @@ + +include $(BASEDIR)/Rules.mk +OBJS = acm_core.o +OBJS += acm_policy.o +OBJS += acm_simple_type_enforcement_hooks.o +OBJS += acm_chinesewall_hooks.o +OBJS += acm_null_hooks.o + +default: acm.o + +acm.o: $(OBJS) + $(LD) $(LDFLAGS) -r -o acm.o $(OBJS) + +clean: + rm -f *.o *~ core diff -uprN xeno-unstable.bk_orig/xen/arch/x86/setup.c xeno-unstable.bk-shype/xen/arch/x86/setup.c --- xeno-unstable.bk_orig/xen/arch/x86/setup.c 2005-06-20 08:51:49.000000000 -0400 +++ xeno-unstable.bk-shype/xen/arch/x86/setup.c 2005-06-20 11:53:17.000000000 -0400 @@ -20,6 +20,7 @@ #include #include #include +#include extern void dmi_scan_machine(void); extern void generic_apic_probe(void); @@ -393,12 +394,17 @@ void __init __start_xen(multiboot_info_t shadow_mode_init(); + /* initialize access control security module */ + acm_init(); + /* Create initial domain 0. */ dom0 = do_createdomain(0, 0); if ( dom0 == NULL ) panic("Error creating domain 0\n"); set_bit(_DOMF_privileged, &dom0->domain_flags); + /* post-create hooks sets security label */ + acm_post_domain0_create(dom0->domain_id); /* Grab the DOM0 command line. */ cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL); diff -uprN xeno-unstable.bk_orig/xen/arch/x86/x86_32/entry.S xeno-unstable.bk-shype/xen/arch/x86/x86_32/entry.S --- xeno-unstable.bk_orig/xen/arch/x86/x86_32/entry.S 2005-06-10 18:04:25.000000000 -0400 +++ xeno-unstable.bk-shype/xen/arch/x86/x86_32/entry.S 2005-06-20 11:53:17.000000000 -0400 @@ -751,6 +751,7 @@ ENTRY(hypercall_table) .long do_boot_vcpu .long do_ni_hypercall /* 25 */ .long do_mmuext_op + .long do_policy_op /* 27 */ .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr diff -uprN xeno-unstable.bk_orig/xen/common/dom0_ops.c xeno-unstable.bk-shype/xen/common/dom0_ops.c --- xeno-unstable.bk_orig/xen/common/dom0_ops.c 2005-06-20 08:51:49.000000000 -0400 +++ xeno-unstable.bk-shype/xen/common/dom0_ops.c 2005-06-20 11:53:17.000000000 -0400 @@ -19,6 +19,7 @@ #include #include #include +#include extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op); extern void arch_getdomaininfo_ctxt( @@ -91,6 +92,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) { long ret = 0; dom0_op_t curop, *op = &curop; + void *ssid = NULL; /* save security ptr between pre and post/fail hooks */ if ( !IS_PRIV(current->domain) ) return -EPERM; @@ -101,6 +103,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op) if ( op->interface_version != DOM0_INTERFACE_VERSION ) return -EACCES; + if ( acm_pre_dom0_op(op, &ssid) ) + return -EACCES; + switch ( op->cmd ) { @@ -357,6 +362,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op) ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) | d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT; + if (d->ssid != NULL) + op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref; + else + op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID; + op->u.getdomaininfo.tot_pages = d->tot_pages; op->u.getdomaininfo.max_pages = d->max_pages; op->u.getdomaininfo.shared_info_frame = @@ -493,7 +503,10 @@ long do_dom0_op(dom0_op_t *u_dom0_op) ret = arch_do_dom0_op(op,u_dom0_op); } - + if (!ret) + acm_post_dom0_op(op, ssid); + else + acm_fail_dom0_op(op, ssid); return ret; } diff -uprN xeno-unstable.bk_orig/xen/common/event_channel.c xeno-unstable.bk-shype/xen/common/event_channel.c --- xeno-unstable.bk_orig/xen/common/event_channel.c 2005-06-06 07:40:20.000000000 -0400 +++ xeno-unstable.bk-shype/xen/common/event_channel.c 2005-06-20 11:53:17.000000000 -0400 @@ -26,6 +26,7 @@ #include #include +#include #define bucket_from_port(d,p) \ ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET]) @@ -587,6 +588,9 @@ long do_event_channel_op(evtchn_op_t *uo if ( copy_from_user(&op, uop, sizeof(op)) != 0 ) return -EFAULT; + if (acm_pre_event_channel(&op)) + return -EACCES; + switch ( op.cmd ) { case EVTCHNOP_alloc_unbound: diff -uprN xeno-unstable.bk_orig/xen/common/grant_table.c xeno-unstable.bk-shype/xen/common/grant_table.c --- xeno-unstable.bk_orig/xen/common/grant_table.c 2005-06-10 07:00:13.000000000 -0400 +++ xeno-unstable.bk-shype/xen/common/grant_table.c 2005-06-20 11:53:17.000000000 -0400 @@ -30,6 +30,7 @@ #include #include #include +#include #define PIN_FAIL(_lbl, _rc, _f, _a...) \ do { \ @@ -357,6 +358,11 @@ __gnttab_map_grant_ref( return GNTST_bad_gntref; } + if (acm_pre_grant_map_ref(dom)) { + (void)__put_user(GNTST_permission_denied, &uop->handle); + return GNTST_permission_denied; + } + if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || unlikely(ld == rd) ) { diff -uprN xeno-unstable.bk_orig/xen/common/policy_ops.c xeno-unstable.bk-shype/xen/common/policy_ops.c --- xeno-unstable.bk_orig/xen/common/policy_ops.c 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/common/policy_ops.c 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,117 @@ +/****************************************************************************** + *policy_ops.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * 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 policy command requests from guest OS. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* function prototypes defined in acm/acm_policy.c */ +int acm_set_policy(void *buf, u16 buf_size, u16 policy); +int acm_get_policy(void *buf, u16 buf_size); +int acm_dump_statistics(void *buf, u16 buf_size); + +typedef enum policyoperation { + POLICY, /* access to policy interface (early drop) */ + GETPOLICY, /* dump policy cache */ + SETPOLICY, /* set policy cache (controls security) */ + DUMPSTATS /* dump policy statistics */ +} policyoperation_t; + +int +acm_authorize_policyops(struct domain *d, policyoperation_t pops) +{ + /* currently, all policy management functions are restricted to privileged domains, + * soon we will introduce finer-grained privileges for policy operations + */ + if (!IS_PRIV(d)) { + printk("%s: Policy management authorization denied ERROR!\n", __func__); + return ACM_ACCESS_DENIED; + } + return ACM_ACCESS_PERMITTED; +} + +long do_policy_op(policy_op_t *u_policy_op) +{ + long ret = 0; + policy_op_t curop, *op = &curop; + + /* check here policy decision for policy commands */ + /* for now allow DOM0 only, later indepedently */ + if (acm_authorize_policyops(current->domain, POLICY)) + return -EACCES; + + if ( copy_from_user(op, u_policy_op, sizeof(*op)) ) + return -EFAULT; + + if ( op->interface_version != POLICY_INTERFACE_VERSION ) + return -EACCES; + + switch ( op->cmd ) + { + case POLICY_SETPOLICY: + { + if (acm_authorize_policyops(current->domain, SETPOLICY)) + return -EACCES; + printkd("%s: setting policy.\n", __func__); + ret = acm_set_policy(op->u.setpolicy.pushcache, op->u.setpolicy.pushcache_size, op->u.setpolicy.policy_type); + if (ret == ACM_OK) + ret = 0; + else + ret = -ESRCH; + } + break; + + case POLICY_GETPOLICY: + { + if (acm_authorize_policyops(current->domain, GETPOLICY)) + return -EACCES; + printkd("%s: getting policy.\n", __func__); + ret = acm_get_policy(op->u.getpolicy.pullcache, op->u.getpolicy.pullcache_size); + if (ret == ACM_OK) + ret = 0; + else + ret = -ESRCH; + } + break; + + case POLICY_DUMPSTATS: + { + if (acm_authorize_policyops(current->domain, DUMPSTATS)) + return -EACCES; + printkd("%s: dumping statistics.\n", __func__); + ret = acm_dump_statistics(op->u.dumpstats.pullcache, op->u.dumpstats.pullcache_size); + if (ret == ACM_OK) + ret = 0; + else + ret = -ESRCH; + } + break; + + default: + ret = -ESRCH; + + } + return ret; +} diff -uprN xeno-unstable.bk_orig/xen/include/acm/acm_core.h xeno-unstable.bk-shype/xen/include/acm/acm_core.h --- xeno-unstable.bk_orig/xen/include/acm/acm_core.h 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/include/acm/acm_core.h 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,117 @@ +/**************************************************************** + * acm_core.h + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * 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 header file describing core data types and constants + * for the access control module and relevant policies + * + */ +#ifndef _ACM_CORE_H +#define _ACM_CORE_H + +#include +#include +#include + +/* Xen-internal representation of the binary policy */ +struct acm_binary_policy { + u16 primary_policy_code; + u16 secondary_policy_code; + void *primary_binary_policy; + void *secondary_binary_policy; + +}; + +struct chwall_binary_policy { + u16 max_types; + u16 max_ssidrefs; + u16 max_conflictsets; + domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */ + domaintype_t *conflict_aggregate_set; /* [max_types] */ + domaintype_t *running_types; /* [max_types] */ + domaintype_t *conflict_sets; /* [max_conflictsets][max_types]*/ +}; + +struct ste_binary_policy { + u16 max_types; + u16 max_ssidrefs; + domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */ + atomic_t ec_eval_count, gt_eval_count; + atomic_t ec_denied_count, gt_denied_count; + atomic_t ec_cachehit_count, gt_cachehit_count; +}; + +/* global acm policy */ +extern struct acm_binary_policy acm_bin_pol; +extern struct chwall_binary_policy chwall_bin_pol; +extern struct ste_binary_policy ste_bin_pol; +/* use the lock when reading / changing binary policy ! */ +extern rwlock_t acm_bin_pol_rwlock; + +/* subject and object type definitions */ +enum acm_datatype { DOMAIN }; + +/* defines number of access decisions to other domains can be cached + * one entry per domain, TE does not distinguish evtchn or grant_table */ +#define ACM_TE_CACHE_SIZE 8 +enum acm_ste_flag { VALID, FREE }; + +/* cache line: + * if cache_line.valid==VALID, then + * STE decision is cached as "permitted" + * on domain cache_line.id + */ +struct acm_ste_cache_line { + enum acm_ste_flag valid; + domid_t id; +}; + +/* general definition of a subject security id */ +struct acm_ssid_domain { + enum acm_datatype datatype; /* type of subject (e.g., partition) */ + ssidref_t ssidref; /* combined security reference */ + void *primary_ssid; /* primary policy ssid part (e.g. chinese wall) */ + void *secondary_ssid; /* secondary policy ssid part (e.g. type enforcement) */ + struct domain *subject; /* backpointer to subject structure */ + domid_t domainid; /* replicate id */ +}; + +/* chinese wall ssid type */ +struct chwall_ssid { + ssidref_t chwall_ssidref; +}; + +/* simple type enforcement ssid type */ +struct ste_ssid { + ssidref_t ste_ssidref; + struct acm_ste_cache_line ste_cache[ACM_TE_CACHE_SIZE]; /* decision cache */ +}; + +/* macros to access ssidref for primary / secondary policy + * primary ssidref = lower 16 bit + * secondary ssidref = higher 16 bit + */ +#define GET_SSIDREF(POLICY, ssidref) \ + ((POLICY) == acm_bin_pol.primary_policy_code) ? \ + ((ssidref) & 0xffff) : ((ssidref) >> 16) + +/* macros to access ssid pointer for primary / secondary policy */ +#define GET_SSIDP(POLICY, ssid) \ + ((POLICY) == acm_bin_pol.primary_policy_code) ? \ + ((ssid)->primary_ssid) : ((ssid)->secondary_ssid) + +/* protos */ +int acm_init_domain_ssid(domid_t id, ssidref_t ssidref); +int acm_free_domain_ssid(struct acm_ssid_domain *ssid); + +#endif + diff -uprN xeno-unstable.bk_orig/xen/include/acm/acm_endian.h xeno-unstable.bk-shype/xen/include/acm/acm_endian.h --- xeno-unstable.bk_orig/xen/include/acm/acm_endian.h 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/include/acm/acm_endian.h 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,88 @@ +/**************************************************************** + * acm_endian.h + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Stefan Berger + * + * Contributions: + * Reiner Sailer + * + * 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 header file defining endian-dependent functions for the + * big-endian policy interface + * + */ +#ifndef _ACM_ENDIAN_H +#define _ACM_ENDIAN_H + +/* don't use these functions in performance critical sections! */ + +/* set during initialization by testing */ +extern u8 little_endian; + +static inline u32 ntohl(u32 x) +{ + if (little_endian) + return + ( (((x) >> 24) & 0xff )| + (((x) >> 8) & 0xff00 )| + (((x) << 8) & 0xff0000 )| + (((x) << 24) & 0xff000000) ); + else + return x; +} + +static inline u16 ntohs(u16 x) +{ + if (little_endian) + return + ( (((x) >> 8) & 0xff )| + (((x) << 8) & 0xff00 ) ); + else + return x; +} + +#define htonl(x) ntohl(x) +#define htons(x) ntohs(x) + +static inline void arrcpy16(u16 *dest, const u16 *src, size_t n) +{ + unsigned int i = 0; + while (i < n) { + dest[i] = htons(src[i]); + i++; + } +} + +static inline void arrcpy32(u32 *dest, const u32 *src, size_t n) +{ + unsigned int i = 0; + while (i < n) { + dest[i] = htonl(src[i]); + i++; + } +} + +static inline void arrcpy(void *dest, const void *src, unsigned int elsize, size_t n) +{ + switch (elsize) { + case sizeof(u16): + arrcpy16((u16 *)dest, (u16 *)src, n); + break; + + case sizeof(u32): + arrcpy32((u32 *)dest, (u32 *)src, n); + break; + + default: + memcpy(dest, src, elsize*n); + } +} + +#endif diff -uprN xeno-unstable.bk_orig/xen/include/acm/acm_hooks.h xeno-unstable.bk-shype/xen/include/acm/acm_hooks.h --- xeno-unstable.bk_orig/xen/include/acm/acm_hooks.h 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/include/acm/acm_hooks.h 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,337 @@ +/**************************************************************** + * acm_hooks.h + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * 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. + * + * acm header file implementing the global (policy-independent) + * sHype hooks that are called throughout Xen. + * + */ +#ifndef _ACM_HOOKS_H +#define _ACM_HOOKS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* if ACM_TRACE_MODE defined, all hooks should + * print a short trace message */ +/* #define ACM_TRACE_MODE */ + +#ifdef ACM_TRACE_MODE +# define traceprintk(fmt, args...) printk(fmt,## args) +#else +# define traceprintk(fmt, args...) +#endif + +/* global variables */ +extern struct acm_operations *acm_primary_ops; +extern struct acm_operations *acm_secondary_ops; + +/********************************************************************************************** + * HOOK structure and meaning (justifies a few words about our model): + * + * General idea: every policy-controlled system operation is reflected in a + * transaction in the system's security state + * + * Keeping the security state consistent requires "atomic" transactions. + * The name of the hooks to place around policy-controlled transactions + * reflects this. If authorizations do not involve security state changes, + * then and only then POST and FAIL hooks remain empty since we don't care + * about the eventual outcome of the operation from a security viewpoint. + * + * PURPOSE of hook types: + * ====================== + * PRE-Hooks + * a) general authorization to guard a controlled system operation + * b) prepare security state change (means: fail hook must be able to "undo" this) + * + * POST-Hooks + * a) commit prepared state change + * + * FAIL-Hooks + * a) roll-back prepared security state change from PRE-Hook + * + * + * PLACEMENT of hook types: + * ======================== + * PRE-Hooks must be called: + * a) before a guarded/controlled system operation is started + * (return is ACM_ACCESS_PERMITTED or ACM_ACCESS_DENIED or error) + * --> operation must be aborted if return is != ACM_ACCESS_PERMITTED + * + * POST-Hooks must be called: + * a) after successful transaction (no return value; commit shall never fail) + * + * FAIL-Hooks must be called: + * a) if system transaction (operation) fails somewhen after calling the PRE-hook + * (obviously the POST-Hook is not called in this case) + * b) if another (secondary) policy denies access in its PRE-Hook + * (policy layering is useful but requires additional handling) + * + * + * + * Hook model from a security transaction viewpoint: + * + * start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success + * (pre-hook) \ (post-hook) + * \ + * fail + * \ + * \ + * roll-back + * (fail-hook) + * \ + * sys-ops error + * + *************************************************************************************************/ + +struct acm_operations { + /* policy management functions (must always be defined!) */ + int (*init_domain_ssid) (void **ssid, ssidref_t ssidref); + void (*free_domain_ssid) (void *ssid); + int (*dump_binary_policy) (u8 *buffer, u16 buf_size); + int (*set_binary_policy) (u8 *buffer, u16 buf_size); + int (*dump_statistics) (u8 *buffer, u16 buf_size); + /* domain management control hooks (can be NULL) */ + int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref); + void (*post_domain_create) (domid_t domid, ssidref_t ssidref); + void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref); + void (*post_domain_destroy) (void *object_ssid, domid_t id); + /* event channel control hooks (can be NULL) */ + int (*pre_eventchannel_unbound) (domid_t id); + void (*fail_eventchannel_unbound) (domid_t id); + int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2); + int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2); + /* grant table control hooks (can be NULL) */ + int (*pre_grant_map_ref) (domid_t id); + void (*fail_grant_map_ref) (domid_t id); + int (*pre_grant_setup) (domid_t id); + void (*fail_grant_setup) (domid_t id); +}; + +static inline int acm_pre_domain_create (void *subject_ssid, ssidref_t ssidref) +{ + if ((acm_primary_ops->pre_domain_create != NULL) && + acm_primary_ops->pre_domain_create (subject_ssid, ssidref)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_domain_create != NULL) && + acm_secondary_ops->pre_domain_create (subject_ssid, ssidref)) { + /* roll-back primary */ + if (acm_primary_ops->fail_domain_create != NULL) + acm_primary_ops->fail_domain_create (subject_ssid, ssidref); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} + +static inline void acm_post_domain_create (domid_t domid, ssidref_t ssidref) +{ + if (acm_primary_ops->post_domain_create != NULL) + acm_primary_ops->post_domain_create (domid, ssidref); + if (acm_secondary_ops->post_domain_create != NULL) + acm_secondary_ops->post_domain_create (domid, ssidref); +} + +static inline void acm_fail_domain_create (void *subject_ssid, ssidref_t ssidref) +{ + if (acm_primary_ops->fail_domain_create != NULL) + acm_primary_ops->fail_domain_create (subject_ssid, ssidref); + if (acm_secondary_ops->fail_domain_create != NULL) + acm_secondary_ops->fail_domain_create (subject_ssid, ssidref); +} + +static inline void acm_post_domain_destroy (void *object_ssid, domid_t id) +{ + if (acm_primary_ops->post_domain_destroy != NULL) + acm_primary_ops->post_domain_destroy (object_ssid, id); + if (acm_secondary_ops->post_domain_destroy != NULL) + acm_secondary_ops->post_domain_destroy (object_ssid, id); + return; +} + +/* event channel ops */ + +static inline int acm_pre_eventchannel_unbound (domid_t id) +{ + if ((acm_primary_ops->pre_eventchannel_unbound != NULL) && + acm_primary_ops->pre_eventchannel_unbound (id)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) && + acm_secondary_ops->pre_eventchannel_unbound (id)) { + /* roll-back primary */ + if (acm_primary_ops->fail_eventchannel_unbound != NULL) + acm_primary_ops->fail_eventchannel_unbound (id); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} + +static inline int acm_pre_eventchannel_interdomain (domid_t id1, domid_t id2) +{ + if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) && + acm_primary_ops->pre_eventchannel_interdomain (id1, id2)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) && + acm_secondary_ops->pre_eventchannel_interdomain (id1, id2)) { + /* roll-back primary */ + if (acm_primary_ops->fail_eventchannel_interdomain != NULL) + acm_primary_ops->fail_eventchannel_interdomain (id1, id2); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} + +/************ Xen inline hooks ***************/ + +/* small macro to make the hooks more readable + * (eliminates hooks if NULL policy is active) + */ +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) +static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid) +{ return 0; } +#else +static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid) +{ + int ret = -EACCES; + struct domain *d; + + switch(op->cmd) { + case DOM0_CREATEDOMAIN: + ret = acm_pre_domain_create(current->domain->ssid, op->u.createdomain.ssidref); + break; + case DOM0_DESTROYDOMAIN: + d = find_domain_by_id(op->u.destroydomain.domain); + if (d != NULL) { + *ssid = d->ssid; /* save for post destroy when d is gone */ + /* no policy-specific hook */ + put_domain(d); + ret = 0; + } + break; + default: + ret = 0; /* ok */ + } + return ret; +} +#endif + + +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) +static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) +{ return; } +#else +static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) +{ + switch(op->cmd) { + case DOM0_CREATEDOMAIN: + /* initialialize shared sHype security labels for new domain */ + acm_init_domain_ssid(op->u.createdomain.domain, op->u.createdomain.ssidref); + acm_post_domain_create(op->u.createdomain.domain, op->u.createdomain.ssidref); + break; + case DOM0_DESTROYDOMAIN: + acm_post_domain_destroy(ssid, op->u.destroydomain.domain); + /* free security ssid for the destroyed domain (also if running null policy */ + acm_free_domain_ssid((struct acm_ssid_domain *)ssid); + break; + } +} +#endif + + +#if (ACM_USE_SECURITY_POLICy == ACM_NULL_POLICY) +static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid) +{ return; } +#else +static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid) +{ + switch(op->cmd) { + case DOM0_CREATEDOMAIN: + acm_fail_domain_create(current->domain->ssid, op->u.createdomain.ssidref); + break; + } +} +#endif + + +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) +static inline int acm_pre_event_channel(evtchn_op_t *op) +{ return 0; } +#else +static inline int acm_pre_event_channel(evtchn_op_t *op) +{ + int ret = -EACCES; + + switch(op->cmd) { + case EVTCHNOP_alloc_unbound: + ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom); + break; + case EVTCHNOP_bind_interdomain: + ret = acm_pre_eventchannel_interdomain(op->u.bind_interdomain.dom1, op->u.bind_interdomain.dom2); + break; + default: + ret = 0; /* ok */ + } + return ret; +} +#endif + +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) +static inline int acm_pre_grant_map_ref(domid_t id) +{ return 0; } +#else +static inline int acm_pre_grant_map_ref (domid_t id) +{ + if ((acm_primary_ops->pre_grant_map_ref != NULL) && + acm_primary_ops->pre_grant_map_ref (id)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_grant_map_ref != NULL) && + acm_secondary_ops->pre_grant_map_ref (id)) { + /* roll-back primary */ + if (acm_primary_ops->fail_grant_map_ref != NULL) + acm_primary_ops->fail_grant_map_ref (id); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} +#endif + + +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) +static inline int acm_pre_grant_setup(domid_t id) +{ return 0; } +#else +static inline int acm_pre_grant_setup (domid_t id) +{ + if ((acm_primary_ops->pre_grant_setup != NULL) && + acm_primary_ops->pre_grant_setup (id)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_grant_setup != NULL) && + acm_secondary_ops->pre_grant_setup (id)) { + /* roll-back primary */ + if (acm_primary_ops->fail_grant_setup != NULL) + acm_primary_ops->fail_grant_setup (id); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} +#endif + + +#endif diff -uprN xeno-unstable.bk_orig/xen/include/public/acm_dom0_setup.h xeno-unstable.bk-shype/xen/include/public/acm_dom0_setup.h --- xeno-unstable.bk_orig/xen/include/public/acm_dom0_setup.h 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/include/public/acm_dom0_setup.h 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,34 @@ +/**************************************************************** + * acm_dom0_setup.h + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * Includes necessary definitions to bring-up dom0 + */ +#include + +extern int acm_init(void); + +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) + +static inline void acm_post_domain0_create(domid_t domid) +{ + return; +} + +#else + +/* predefined ssidref for DOM0 used by xen when creating DOM0 */ +#define ACM_DOM0_SSIDREF 0 + +static inline void acm_post_domain0_create(domid_t domid) +{ + /* initialialize shared sHype security labels for new domain */ + acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF); + acm_post_domain_create(domid, ACM_DOM0_SSIDREF); +} + +#endif diff -uprN xeno-unstable.bk_orig/xen/include/public/acm.h xeno-unstable.bk-shype/xen/include/public/acm.h --- xeno-unstable.bk_orig/xen/include/public/acm.h 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/include/public/acm.h 2005-06-20 11:53:50.000000000 -0400 @@ -0,0 +1,161 @@ +/**************************************************************** + * acm.h + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * Contributors: + * Stefan Berger + * added network byte order support for 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 general access control module header file. + * here are all definitions that are shared between + * xen-core, guest-kernels, and applications. + * + * todo: move from static policy choice to compile option. + */ + +#ifndef _XEN_PUBLIC_SHYPE_H +#define _XEN_PUBLIC_SHYPE_H + +#include "xen.h" +#include "sched_ctl.h" + +/* if ACM_DEBUG defined, all hooks should + * print a short trace message (comment it out + * when not in testing mode ) + */ +/* #define ACM_DEBUG */ + +#ifdef ACM_DEBUG +# define printkd(fmt, args...) printk(fmt,## args) +#else +# define printkd(fmt, args...) +#endif + +/* default ssid reference value if not supplied */ +#define ACM_DEFAULT_SSID 0xffffffff +#define ACM_DEFAULT_LOCAL_SSID 0xffff + +/* Internal ACM ERROR types */ +#define ACM_OK 0 +#define ACM_UNDEF -1 +#define ACM_INIT_SSID_ERROR -2 +#define ACM_INIT_SOID_ERROR -3 +#define ACM_ERROR -4 + +/* External ACCESS DECISIONS */ +#define ACM_ACCESS_PERMITTED 0 +#define ACM_ACCESS_DENIED -111 +#define ACM_NULL_POINTER_ERROR -200 + +#define ACM_MAX_POLICY 3 + +#define ACM_NULL_POLICY 0 +#define ACM_CHINESE_WALL_POLICY 1 +#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2 +#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3 + +/* policy: */ +#define ACM_POLICY_NAME(X) \ + (X == ACM_NULL_POLICY) ? "NULL policy" : \ + (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \ + (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT policy" : \ + (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \ + "UNDEFINED policy" + +#ifndef ACM_USE_SECURITY_POLICY +#define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY +#endif + +/* defines a ssid reference used by xen */ +typedef u32 ssidref_t; + +/* -------security policy relevant type definitions-------- */ + +/* type identifier; compares to "equal" or "not equal" */ +typedef u16 domaintype_t; + +/* CHINESE WALL POLICY DATA STRUCTURES + * + * current accumulated conflict type set: + * When a domain is started and has a type that is in + * a conflict set, the conflicting types are incremented in + * the aggregate set. When a domain is destroyed, the + * conflicting types to its type are decremented. + * If a domain has multiple types, this procedure works over + * all those types. + * + * conflict_aggregate_set[i] holds the number of + * running domains that have a conflict with type i. + * + * running_types[i] holds the number of running domains + * that include type i in their ssidref-referenced type set + * + * conflict_sets[i][j] is "0" if type j has no conflict + * with type i and is "1" otherwise. + */ +/* high-16 = version, low-16 = check magic */ +#define ACM_MAGIC 0x0001debc + +/* each offset in bytes from start of the struct they + * the are part of */ +/* each buffer consists of all policy information for + * the respective policy given in the policy code + */ +struct acm_policy_buffer { + u32 magic; + u32 policyversion; + u32 len; + u16 primary_policy_code; + u16 primary_buffer_offset; + u16 secondary_policy_code; + u16 secondary_buffer_offset; +}; + +struct acm_chwall_policy_buffer { + u16 policy_code; + u16 chwall_max_types; + u16 chwall_max_ssidrefs; + u16 chwall_max_conflictsets; + u16 chwall_ssid_offset; + u16 chwall_conflict_sets_offset; + u16 chwall_running_types_offset; + u16 chwall_conflict_aggregate_offset; +}; + +struct acm_ste_policy_buffer { + u16 policy_code; + u16 ste_max_types; + u16 ste_max_ssidrefs; + u16 ste_ssid_offset; +}; + +struct acm_stats_buffer { + u32 magic; + u32 policyversion; + u32 len; + u16 primary_policy_code; + u16 primary_stats_offset; + u16 secondary_policy_code; + u16 secondary_stats_offset; +}; + +struct acm_ste_stats_buffer { + u32 ec_eval_count; + u32 gt_eval_count; + u32 ec_denied_count; + u32 gt_denied_count; + u32 ec_cachehit_count; + u32 gt_cachehit_count; +}; + + +#endif diff -uprN xeno-unstable.bk_orig/xen/include/public/dom0_ops.h xeno-unstable.bk-shype/xen/include/public/dom0_ops.h --- xeno-unstable.bk_orig/xen/include/public/dom0_ops.h 2005-06-06 07:40:20.000000000 -0400 +++ xeno-unstable.bk-shype/xen/include/public/dom0_ops.h 2005-06-20 11:53:17.000000000 -0400 @@ -43,6 +43,8 @@ typedef struct sched_adjdom_cmd dom0_adj #define DOM0_CREATEDOMAIN 8 typedef struct { + /* IN parameters */ + u32 ssidref; /* IN/OUT parameters. */ /* Identifier for new domain (auto-allocate if zero is specified). */ domid_t domain; @@ -88,6 +90,7 @@ typedef struct { u32 n_vcpu; s32 vcpu_to_cpu[MAX_VIRT_CPUS]; /* current mapping */ cpumap_t cpumap[MAX_VIRT_CPUS]; /* allowable mapping */ + u32 ssidref; } dom0_getdomaininfo_t; #define DOM0_SETDOMAININFO 13 diff -uprN xeno-unstable.bk_orig/xen/include/public/policy_ops.h xeno-unstable.bk-shype/xen/include/public/policy_ops.h --- xeno-unstable.bk_orig/xen/include/public/policy_ops.h 1969-12-31 19:00:00.000000000 -0500 +++ xeno-unstable.bk-shype/xen/include/public/policy_ops.h 2005-06-20 11:53:17.000000000 -0400 @@ -0,0 +1,74 @@ +/****************************************************************************** + * policy_ops.h + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * 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 policy command requests from guest OS. + * access checked by policy; not restricted to DOM0 + * + */ + + +#ifndef __XEN_PUBLIC_POLICY_OPS_H__ +#define __XEN_PUBLIC_POLICY_OPS_H__ + +#include "xen.h" +#include "sched_ctl.h" + +/* + * Make sure you increment the interface version whenever you modify this file! + * This makes sure that old versions of policy tools will stop working in a + * well-defined way (rather than crashing the machine, for instance). + */ +#define POLICY_INTERFACE_VERSION 0xAAAA0001 + +/************************************************************************/ + +#define POLICY_SETPOLICY 4 +typedef struct { + /* IN variables. */ + u16 policy_type; + u16 padding1; + /* OUT variables */ + void *pushcache; + u16 pushcache_size; +} PACKED policy_setpolicy_t; + + +#define POLICY_GETPOLICY 5 +typedef struct { + /* IN variables. */ + u16 policy_type; + u16 padding1; + /* OUT variables */ + void *pullcache; + u16 pullcache_size; +} PACKED policy_getpolicy_t; + +#define POLICY_DUMPSTATS 6 +typedef struct { + void *pullcache; + u16 pullcache_size; +} PACKED policy_dumpstats_t; + + +typedef struct { + u32 cmd; /* 0 */ + u32 interface_version; /* 4 */ /* POLICY_INTERFACE_VERSION */ + union { /* 8 */ + u32 dummy[14]; /* 72bytes */ + policy_setpolicy_t setpolicy; + policy_getpolicy_t getpolicy; + policy_dumpstats_t dumpstats; + } PACKED u; +} PACKED policy_op_t; /* 80 bytes */ + +#endif /* __XEN_PUBLIC_POLICY_OPS_H__ */ diff -uprN xeno-unstable.bk_orig/xen/include/public/xen.h xeno-unstable.bk-shype/xen/include/public/xen.h --- xeno-unstable.bk_orig/xen/include/public/xen.h 2005-06-20 08:51:49.000000000 -0400 +++ xeno-unstable.bk-shype/xen/include/public/xen.h 2005-06-20 11:53:17.000000000 -0400 @@ -58,6 +58,7 @@ #define __HYPERVISOR_boot_vcpu 24 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ #define __HYPERVISOR_mmuext_op 26 +#define __HYPERVISOR_policy_op 27 /* * VIRTUAL INTERRUPTS diff -uprN xeno-unstable.bk_orig/xen/include/xen/sched.h xeno-unstable.bk-shype/xen/include/xen/sched.h --- xeno-unstable.bk_orig/xen/include/xen/sched.h 2005-06-08 07:42:38.000000000 -0400 +++ xeno-unstable.bk-shype/xen/include/xen/sched.h 2005-06-20 11:53:17.000000000 -0400 @@ -137,6 +137,8 @@ struct domain cpumask_t cpumask; struct arch_domain arch; + + void *ssid; /* sHype security subject identifier */ }; struct domain_setup_info diff -uprN xeno-unstable.bk_orig/xen/Makefile xeno-unstable.bk-shype/xen/Makefile --- xeno-unstable.bk_orig/xen/Makefile 2005-06-06 07:40:20.000000000 -0400 +++ xeno-unstable.bk-shype/xen/Makefile 2005-06-20 11:53:17.000000000 -0400 @@ -46,6 +46,7 @@ clean: delete-unfresh-files $(MAKE) -C tools clean $(MAKE) -C common clean $(MAKE) -C drivers clean + $(MAKE) -C acm clean $(MAKE) -C arch/$(TARGET_ARCH) clean rm -f include/asm *.o $(TARGET)* *~ core rm -f include/asm-*/asm-offsets.h @@ -58,6 +59,7 @@ $(TARGET): delete-unfresh-files $(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h $(MAKE) -C common $(MAKE) -C drivers + $(MAKE) -C acm $(MAKE) -C arch/$(TARGET_ARCH) # drivers/char/console.o may contain static banner/compile info. Blow it away. @@ -109,7 +111,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h .PHONY: default debug install dist clean delete-unfresh-files TAGS tags -SUBDIRS = arch/$(TARGET_ARCH) common drivers +SUBDIRS = acm arch/$(TARGET_ARCH) common drivers define all_sources ( find include/asm-$(TARGET_ARCH) -name SCCS -prune -o -name '*.h' -print; \ find include -type d -name SCCS -prune -o \( -name "asm-*" -o \ diff -uprN xeno-unstable.bk_orig/xen/Rules.mk xeno-unstable.bk-shype/xen/Rules.mk --- xeno-unstable.bk_orig/xen/Rules.mk 2005-06-06 07:40:20.000000000 -0400 +++ xeno-unstable.bk-shype/xen/Rules.mk 2005-06-20 11:53:17.000000000 -0400 @@ -35,6 +35,7 @@ OBJS += $(patsubst %.c,%.o,$(C_SRCS)) ALL_OBJS := $(BASEDIR)/common/common.o ALL_OBJS += $(BASEDIR)/drivers/char/driver.o ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o +ALL_OBJS += $(BASEDIR)/acm/acm.o ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o