diff -r df02b4fbb1b8 -r db5ba3cb54ee Config.mk --- a/Config.mk Wed Mar 7 16:19:29 2007 -0500 +++ b/Config.mk Wed Mar 7 16:22:43 2007 -0500 @@ -58,9 +58,9 @@ CFLAGS += $(foreach i, $(EXTRA_INCLUDES) #Enable XSM security module. Enabling XSM requires selection of an #XSM security module. -XSM_ENABLE ?= y +XSM_ENABLE ?= n ifeq ($(XSM_ENABLE),y) -FLASK_ENABLE ?= y +FLASK_ENABLE ?= n ifeq ($(FLASK_ENABLE),y) FLASK_DEVELOP ?= y FLASK_BOOTPARAM ?= y diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/Rules.mk --- a/xen/Rules.mk Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/Rules.mk Wed Mar 7 16:22:43 2007 -0500 @@ -58,7 +58,7 @@ CFLAGS-$(FLASK_DEVELOP) += -DFLASK_DEV CFLAGS-$(FLASK_DEVELOP) += -DFLASK_DEVELOP CFLAGS-$(FLASK_BOOTPARAM) += -DFLASK_BOOTPARAM CFLAGS-$(FLASK_AVC_STATS) += -DFLASK_AVC_STATS -CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY +CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY -DXSM_MAGIC=0x0100bcde CFLAGS-$(verbose) += -DVERBOSE CFLAGS-$(crash_debug) += -DCRASH_DEBUG CFLAGS-$(perfc) += -DPERF_COUNTERS diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/acm/Makefile --- a/xen/acm/Makefile Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/acm/Makefile Wed Mar 7 16:22:43 2007 -0500 @@ -3,3 +3,4 @@ obj-y += acm_simple_type_enforcement_hoo 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 diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/acm/acm_core.c --- a/xen/acm/acm_core.c Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/acm/acm_core.c Wed Mar 7 16:22:43 2007 -0500 @@ -31,6 +31,7 @@ #include #include #include +#include /* debug: * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE; @@ -48,6 +49,8 @@ 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; @@ -187,44 +190,11 @@ acm_is_policy(char *buf, unsigned long l return be32_to_cpu(pol->magic) == ACM_MAGIC; } - -static int -acm_setup(char *policy_start, - unsigned long policy_len) -{ - 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); - 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(char *policy_start, - unsigned long policy_len) +static __init int acm_init(void) { int ret = ACM_OK; - /* first try to load the boot policy (uses its own locks) */ - acm_setup(policy_start, policy_len); + printk("ACM-XSM: Initializing.\n"); if (acm_active_security_policy != ACM_POLICY_UNDEFINED) { @@ -253,8 +223,14 @@ acm_init(char *policy_start, /* 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(domid_t id, ssidref_t ssidref) diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/arch/x86/setup.c Wed Mar 7 16:22:43 2007 -0500 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -210,44 +209,6 @@ static void __init percpu_free_unused_ar #endif } -/* Fetch acm policy module from multiboot modules. */ -static void extract_acm_policy( - multiboot_info_t *mbi, - unsigned int *initrdidx, - char **_policy_start, - unsigned long *_policy_len) -{ - int i; - module_t *mod = (module_t *)__va(mbi->mods_addr); - unsigned long start, policy_len; - char *policy_start; - - /* - * Try all modules and see whichever could be the binary policy. - * Adjust the initrdidx if module[1] is the binary policy. - */ - for ( i = mbi->mods_count-1; i >= 1; i-- ) - { - start = initial_images_start + (mod[i].mod_start-mod[0].mod_start); -#if defined(__i386__) - policy_start = (char *)start; -#elif defined(__x86_64__) - policy_start = __va(start); -#endif - policy_len = mod[i].mod_end - mod[i].mod_start; - if ( acm_is_policy(policy_start, policy_len) ) - { - printk("Policy len 0x%lx, start at %p - module %d.\n", - policy_len, policy_start, i); - *_policy_start = policy_start; - *_policy_len = policy_len; - if ( i == 1 ) - *initrdidx = (mbi->mods_count > 2) ? 2 : 0; - break; - } - } -} - static void __init init_idle_domain(void) { struct domain *idle_domain; @@ -298,8 +259,6 @@ void __init __start_xen(multiboot_info_t char __cmdline[] = "", *cmdline = __cmdline; unsigned long _initrd_start = 0, _initrd_len = 0; unsigned int initrdidx = 1; - char *_policy_start = NULL; - unsigned long _policy_len = 0; module_t *mod = (module_t *)__va(mbi->mods_addr); unsigned long nr_pages, modules_length; paddr_t s, e; @@ -725,21 +684,12 @@ void __init __start_xen(multiboot_info_t if ( opt_watchdog ) watchdog_enable(); - /* Extract policy from multiboot. */ - extract_acm_policy(mbi, &initrdidx, &_policy_start, &_policy_len); - - /* initialize access control security module */ - acm_init(_policy_start, _policy_len); - /* Create initial domain 0. */ dom0 = domain_create(0, 0); if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) ) panic("Error creating domain 0\n"); dom0->is_privileged = 1; - - /* Post-create hook sets security label. */ - acm_post_domain0_create(dom0->domain_id); xsm_complete_init(dom0); diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/arch/x86/x86_32/entry.S Wed Mar 7 16:22:43 2007 -0500 @@ -660,7 +660,7 @@ ENTRY(hypercall_table) .long do_vcpu_op .long do_ni_hypercall /* 25 */ .long do_mmuext_op - .long do_acm_op + .long do_xsm_op .long do_nmi_op .long do_sched_op .long do_callback_op /* 30 */ @@ -671,7 +671,6 @@ ENTRY(hypercall_table) .long do_sysctl /* 35 */ .long do_domctl .long do_kexec_op - .long do_xsm_op .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -704,7 +703,7 @@ ENTRY(hypercall_args_table) .byte 3 /* do_vcpu_op */ .byte 0 /* do_ni_hypercall */ /* 25 */ .byte 4 /* do_mmuext_op */ - .byte 1 /* do_acm_op */ + .byte 1 /* do_xsm_op */ .byte 2 /* do_nmi_op */ .byte 2 /* do_sched_op */ .byte 2 /* do_callback_op */ /* 30 */ @@ -715,7 +714,6 @@ ENTRY(hypercall_args_table) .byte 1 /* do_sysctl */ /* 35 */ .byte 1 /* do_domctl */ .byte 2 /* do_kexec_op */ - .byte 1 /* do_xsm_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/common/domctl.c --- a/xen/common/domctl.c Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/common/domctl.c Wed Mar 7 16:22:43 2007 -0500 @@ -23,7 +23,6 @@ #include #include #include -#include #include extern long arch_do_domctl( @@ -123,11 +122,6 @@ void getdomaininfo(struct domain *d, str if ( is_hvm_domain(d) ) info->flags |= XEN_DOMINF_hvm_guest; - if ( d->ssid != NULL ) - info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref; - else - info->ssidref = ACM_DEFAULT_SSID; - xsm_security_domaininfo(d, info); info->tot_pages = d->tot_pages; @@ -179,7 +173,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc { long ret = 0; struct xen_domctl curop, *op = &curop; - void *ssid = NULL; /* save security ptr between pre and post/fail hooks */ static DEFINE_SPINLOCK(domctl_lock); if ( !IS_PRIV(current->domain) ) @@ -190,9 +183,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION ) return -EACCES; - - if ( acm_pre_domctl(op, &ssid) ) - return -EPERM; spin_lock(&domctl_lock); @@ -819,11 +809,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc spin_unlock(&domctl_lock); - if ( ret == 0 ) - acm_post_domctl(op, &ssid); - else - acm_fail_domctl(op, &ssid); - return ret; } diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/common/event_channel.c --- a/xen/common/event_channel.c Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/common/event_channel.c Wed Mar 7 16:22:43 2007 -0500 @@ -29,7 +29,6 @@ #include #include -#include #include #define bucket_from_port(d,p) \ @@ -111,9 +110,6 @@ static long evtchn_alloc_unbound(evtchn_ domid_t dom = alloc->dom; long rc; - if ( (rc = acm_pre_eventchannel_unbound(dom, alloc->remote_dom)) != 0 ) - return rc; - if ( dom == DOMID_SELF ) dom = current->domain->domain_id; else if ( !IS_PRIV(current->domain) ) @@ -154,9 +150,6 @@ static long evtchn_bind_interdomain(evtc int lport, rport = bind->remote_port; domid_t rdom = bind->remote_dom; long rc; - - if ( (rc = acm_pre_eventchannel_interdomain(rdom)) != 0 ) - return rc; if ( rdom == DOMID_SELF ) rdom = current->domain->domain_id; diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/common/grant_table.c --- a/xen/common/grant_table.c Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/common/grant_table.c Wed Mar 7 16:22:43 2007 -0500 @@ -33,7 +33,6 @@ #include #include #include -#include #include #ifndef max_nr_grant_frames @@ -200,12 +199,6 @@ __gnttab_map_grant_ref( { gdprintk(XENLOG_INFO, "Bad flags in grant map op (%x).\n", op->flags); op->status = GNTST_bad_gntref; - return; - } - - if ( acm_pre_grant_map_ref(op->dom) ) - { - op->status = GNTST_permission_denied; return; } diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/include/acm/acm_hooks.h --- a/xen/include/acm/acm_hooks.h Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/include/acm/acm_hooks.h Wed Mar 7 16:22:43 2007 -0500 @@ -370,8 +370,6 @@ static inline int acm_sharing(ssidref_t } -extern int acm_init(char *policy_start, unsigned long policy_len); - /* Return true iff buffer has an acm policy magic number. */ extern int acm_is_policy(char *buf, unsigned long len); diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/include/public/xen.h --- a/xen/include/public/xen.h Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/include/public/xen.h Wed Mar 7 16:22:43 2007 -0500 @@ -69,7 +69,7 @@ #define __HYPERVISOR_vcpu_op 24 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ #define __HYPERVISOR_mmuext_op 26 -#define __HYPERVISOR_acm_op 27 +#define __HYPERVISOR_xsm_op 27 #define __HYPERVISOR_nmi_op 28 #define __HYPERVISOR_sched_op 29 #define __HYPERVISOR_callback_op 30 @@ -80,7 +80,6 @@ #define __HYPERVISOR_sysctl 35 #define __HYPERVISOR_domctl 36 #define __HYPERVISOR_kexec_op 37 -#define __HYPERVISOR_xsm_op 38 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/include/xen/hypercall.h --- a/xen/include/xen/hypercall.h Wed Mar 7 16:19:29 2007 -0500 +++ b/xen/include/xen/hypercall.h Wed Mar 7 16:22:43 2007 -0500 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -98,8 +97,9 @@ do_vcpu_op( XEN_GUEST_HANDLE(void) arg); extern long -do_acm_op( - int cmd, XEN_GUEST_HANDLE(void) arg); +do_xsm_op( + int cmd, + XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op); extern long do_nmi_op( @@ -126,9 +126,4 @@ compat_memory_op( #endif -extern long -do_xsm_op( - int cmd, - XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op); - #endif /* __XEN_HYPERCALL_H__ */ diff -r df02b4fbb1b8 -r db5ba3cb54ee xen/acm/acm_xsm_hooks.c --- /dev/null Thu Jan 1 00:00:00 1970 +0000 +++ b/xen/acm/acm_xsm_hooks.c Wed Mar 7 16:22:43 2007 -0500 @@ -0,0 +1,195 @@ +/**************************************************************** + * acm_xsm_hooks.c + * + * Copyright (C) 2005 IBM Corporation + * + * Author: + * Reiner Sailer + * + * Contributors: + * Michael LeMay, + * George Coker, + * + * 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 +#include +#include + +static int acm_createdomain (struct xen_domctl *op) +{ + void *subject_ssid = current->domain->ssid; + ssidref_t ssidref = op->u.createdomain.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 void acm_createdomain_post (struct domain *d, struct xen_domctl *op) +{ + ssidref_t ssidref = op->u.createdomain.ssidref; + + /* initialialize shared sHype security labels for new domain */ + acm_init_domain_ssid(d->domain_id, ssidref); + + if (acm_primary_ops->post_domain_create != NULL) + acm_primary_ops->post_domain_create(d->domain_id, ssidref); + if (acm_secondary_ops->post_domain_create != NULL) + acm_secondary_ops->post_domain_create(d->domain_id, ssidref); +} + +static int acm_destroydomain (struct domain *d) +{ + int ret = -EACCES; + void *ssid = NULL; + + if (d != NULL) { + ssid = d->ssid; + + if (ssid == NULL) { + printk("%s: Warning. Destroying domain without ssid pointer.\n", __func__); + return -EACCES; + } + + ret = 0; + } + + return ret; +} + +static void acm_destroydomain_post (struct domain *d) +{ + domid_t id = d->domain_id; + + if (acm_primary_ops->post_domain_destroy != NULL) + acm_primary_ops->post_domain_destroy(d->ssid, id); + if (acm_secondary_ops->post_domain_destroy != NULL) + acm_secondary_ops->post_domain_destroy(d->ssid, id); + + /* free security ssid for the destroyed domain (also if null policy */ + acm_free_domain_ssid((struct acm_ssid_domain *)(d->ssid)); + d->ssid = NULL; +} + +static void acm_createdomain_fail (struct xen_domctl *op) +{ + acm_fail_domain_create( + current->domain->ssid, op->u.createdomain.ssidref); +} + +static int acm_grant_mapref (struct domain *ld, struct domain *rd, + uint32_t flags) +{ + domid_t id = rd->domain_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; + } +} + +static int acm_evtchn_unbound (struct domain *d1, struct evtchn *chn1, domid_t id2) +{ + domid_t id1 = d1->domain_id; + + if ((acm_primary_ops->pre_eventchannel_unbound != NULL) && + acm_primary_ops->pre_eventchannel_unbound(id1, id2)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) && + acm_secondary_ops->pre_eventchannel_unbound(id1, id2)) { + /* roll-back primary */ + if (acm_primary_ops->fail_eventchannel_unbound != NULL) + acm_primary_ops->fail_eventchannel_unbound(id1, id2); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} + +static int acm_evtchn_interdomain (struct domain *d1, struct evtchn *chn1, + struct domain *d2, struct evtchn *chn2) +{ + domid_t id2 = d2->domain_id; + + if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) && + acm_primary_ops->pre_eventchannel_interdomain(id2)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) && + acm_secondary_ops->pre_eventchannel_interdomain(id2)) { + /* roll-back primary */ + if (acm_primary_ops->fail_eventchannel_interdomain != NULL) + acm_primary_ops->fail_eventchannel_interdomain(id2); + return ACM_ACCESS_DENIED; + } else + return ACM_ACCESS_PERMITTED; +} + +static void acm_complete_init (struct domain *dom0) +{ + domid_t domid = dom0->domain_id; + + acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF); + + if (acm_primary_ops->post_domain_create != NULL) + acm_primary_ops->post_domain_create(domid, ACM_DOM0_SSIDREF); + if (acm_secondary_ops->post_domain_create != NULL) + acm_secondary_ops->post_domain_create(domid, ACM_DOM0_SSIDREF); + +} + +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(int cmd, XEN_GUEST_HANDLE(xsm_op_t) arg); + +struct xsm_operations acm_xsm_ops = { + .createdomain = acm_createdomain, + .createdomain_post = acm_createdomain_post, + .createdomain_fail = acm_createdomain_fail, + .destroydomain = acm_destroydomain, + .free_security_domain = acm_destroydomain_post, + + .grant_mapref = acm_grant_mapref, + + .evtchn_unbound = acm_evtchn_unbound, + .evtchn_interdomain = acm_evtchn_interdomain, + .complete_init = acm_complete_init, + + .security_domaininfo = acm_security_domaininfo, + + .__do_xsm_op = do_acm_op, +};