* George S. Coker, II (gscoker@xxxxxxxxxxxxxx) wrote:
> The attached patch implements the Xen Security Modules (XSM) framework.
> This patch should apply cleanly to changeset 9694:d82a4c4d04d4 Xen
> 3.0.2-3.
Nice to see this all posted. Have any perfomance numbers for default
dummy, or numbers for increase in memory footprint for this + flask +
flask example policy? Just curious to see what the rough cost is.
Some quick comments below.
> Modules may also define at Xen compile time a magic number XSM_MAGIC to
> indicate that a policy should be discovered from the images loaded at
> boot. The policy file should then be listed in grub as one of the
> multi-boot modules after the dom0 kernel.
I like that feature.
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/arch/x86/dom0_ops.c
> --- a/xen/arch/x86/dom0_ops.c Fri May 26 09:23:33 2006 +0100
> +++ b/xen/arch/x86/dom0_ops.c Thu Aug 31 17:14:49 2006 -0400
> @@ -25,6 +25,7 @@
> #include <asm/hvm/support.h>
> #include <asm/processor.h>
> #include <public/sched_ctl.h>
> +#include <xsm/xsm.h>
>
> #include <asm/mtrr.h>
> #include "cpu/mtrr/mtrr.h"
> @@ -58,6 +59,10 @@ long arch_do_dom0_op(struct dom0_op *op,
>
> case DOM0_MSR:
> {
> + ret = xsm_msr(op->u.msr.write);
Hmm, this is against 3.0.2, unfortunately you'll have some work to move
to 3.0.3 with the hypercall changes here (IIRC, this one actually
went away). And have you done each arch? I only see x86 here.
<snip>
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/arch/x86/setup.c
> --- a/xen/arch/x86/setup.c Fri May 26 09:23:33 2006 +0100
> +++ b/xen/arch/x86/setup.c Thu Aug 31 17:14:49 2006 -0400
> @@ -24,6 +24,7 @@
> #include <asm/shadow.h>
> #include <asm/e820.h>
> #include <acm/acm_hooks.h>
> +#include <xsm/xsm.h>
>
> extern void dmi_scan_machine(void);
> extern void generic_apic_probe(void);
> @@ -404,6 +405,8 @@ void __init __start_xen(multiboot_info_t
>
> scheduler_init();
>
> + xsm_init(&initrdidx, mbi, initial_images_start);
> +
> idle_domain = domain_create(IDLE_DOMAIN_ID, 0);
> BUG_ON(idle_domain == NULL);
>
> @@ -507,6 +510,8 @@ void __init __start_xen(multiboot_info_t
> set_bit(_DOMF_privileged, &dom0->domain_flags);
> /* post-create hooks sets security label */
> acm_post_domain0_create(dom0->domain_id);
> +
> + xsm_complete_init(dom0);
Seems this should drop the acm hook here, no?
> /* Grab the DOM0 command line. */
> cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/arch/x86/x86_32/entry.S
> --- a/xen/arch/x86/x86_32/entry.S Fri May 26 09:23:33 2006 +0100
> +++ b/xen/arch/x86/x86_32/entry.S Thu Aug 31 17:14:49 2006 -0400
> @@ -648,6 +648,7 @@ ENTRY(hypercall_table)
> .long do_acm_op
> .long do_nmi_op
> .long do_arch_sched_op
> + .long do_xsm_op /* 30 */
> .rept NR_hypercalls-((.-hypercall_table)/4)
> .long do_ni_hypercall
> .endr
> @@ -683,6 +684,7 @@ ENTRY(hypercall_args_table)
> .byte 1 /* do_acm_op */
> .byte 2 /* do_nmi_op */
> .byte 2 /* do_arch_sched_op */
> + .byte 1 /* do_xsm_op */
> .rept NR_hypercalls-(.-hypercall_args_table)
> .byte 0 /* do_ni_hypercall */
> .endr
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/arch/x86/x86_32/xen.lds.S
> --- a/xen/arch/x86/x86_32/xen.lds.S Fri May 26 09:23:33 2006 +0100
> +++ b/xen/arch/x86/x86_32/xen.lds.S Thu Aug 31 17:14:49 2006 -0400
> @@ -56,6 +56,7 @@ SECTIONS
> __initcall_start = .;
> .initcall.init : { *(.initcall.init) } :text
> __initcall_end = .;
> + .xsm_initcall.init : { __xsm_initcall_start = .; *(.xsm_initcall.init)
> __xsm_initcall_end = .; }
> . = ALIGN(STACK_SIZE);
> __init_end = .;
>
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/common/dom0_ops.c
> --- a/xen/common/dom0_ops.c Fri May 26 09:23:33 2006 +0100
> +++ b/xen/common/dom0_ops.c Thu Aug 31 17:14:49 2006 -0400
> @@ -22,6 +22,7 @@
> #include <public/dom0_ops.h>
> #include <public/sched_ctl.h>
> #include <acm/acm_hooks.h>
> +#include <xsm/xsm.h>
>
> extern long arch_do_dom0_op(
> struct dom0_op *op, GUEST_HANDLE(dom0_op_t) u_dom0_op);
> @@ -82,6 +83,8 @@ static void getdomaininfo(struct domain
> 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;
> info->max_pages = d->max_pages;
> @@ -120,7 +123,12 @@ long do_dom0_op(GUEST_HANDLE(dom0_op_t)
shouldn't this take care of the acm_pre_dom0_op hook here as well?
IOW, at the end there shouldn't be acm specific hooks left, right?
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/common/domain.c
> --- a/xen/common/domain.c Fri May 26 09:23:33 2006 +0100
> +++ b/xen/common/domain.c Thu Aug 31 17:14:49 2006 -0400
> @@ -24,6 +24,7 @@
> #include <public/dom0_ops.h>
> #include <public/sched.h>
> #include <public/vcpu.h>
> +#include <xsm/xsm.h>
>
> /* Both these structures are protected by the domlist_lock. */
> rwlock_t domlist_lock = RW_LOCK_UNLOCKED;
> @@ -50,6 +51,9 @@ struct domain *domain_create(domid_t dom
> INIT_LIST_HEAD(&d->xenpage_list);
>
> rangeset_domain_initialise(d);
> +
> + if (xsm_alloc_security_domain(d))
> + goto fail1;
>
> if ( !is_idle_domain(d) )
> {
> @@ -305,6 +309,8 @@ void domain_destroy(struct domain *d)
>
> arch_domain_destroy(d);
>
> + xsm_free_security_domain(d);
> +
> free_domain(d);
>
> send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/include/xen/grant_table.h
> --- a/xen/include/xen/grant_table.h Fri May 26 09:23:33 2006 +0100
> +++ b/xen/include/xen/grant_table.h Thu Aug 31 17:14:49 2006 -0400
> @@ -74,6 +74,7 @@ typedef struct {
> grant_entry_t *shared;
> /* Active grant table. */
> active_grant_entry_t *active;
> + void *security;
What's a grant table label look like?
> /* Mapping tracking table. */
> grant_mapping_t *maptrack;
> unsigned int maptrack_head;
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/include/xen/hypercall.h
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/include/xen/sched.h
> --- a/xen/include/xen/sched.h Fri May 26 09:23:33 2006 +0100
> +++ b/xen/include/xen/sched.h Thu Aug 31 17:14:49 2006 -0400
> @@ -47,6 +47,7 @@ struct evtchn
> u16 pirq; /* state == ECS_PIRQ */
> u16 virq; /* state == ECS_VIRQ */
> } u;
> + void *ssid;
> };
Ah, you must resue the acm domain label? Actually would be nice to see
which objects are labelled, did I miss that list?
> int evtchn_init(struct domain *d);
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/include/xsm/xsm.h
> --- /dev/null Thu Jan 1 00:00:00 1970 +0000
> +++ b/xen/include/xsm/xsm.h Thu Aug 31 17:14:49 2006 -0400
> @@ -0,0 +1,722 @@
> +/*
> + * This file contains the Flask hook function implementations for Xen.
> + *
> + * This work is based on the LSM implementation in Linux 2.6.13.4.
> + *
> + * Author: George Coker, <gscoker@xxxxxxxxxxxxxx>
> + *
> + * Contributors: Michael LeMay, <mdlemay@xxxxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2,
> + * as published by the Free Software Foundation.
> + */
> +
> +#ifndef __XSM_H__
> +#define __XSM_H__
> +
> +#include <xen/sched.h>
> +#include <xen/multiboot.h>
> +
> +#ifdef XSM_ENABLE
> +
> +/* policy magic number (defined by XSM_MAGIC) */
> +typedef u32 xsm_magic_t;
> +#ifndef XSM_MAGIC
> +#define XSM_MAGIC 0x00000000
> +#endif
> +
> +extern char *policy_buffer;
> +extern u32 policy_size;
> +
> +typedef void xsm_op_t;
> +DEFINE_GUEST_HANDLE(xsm_op_t);
> +
> +typedef int (*xsm_initcall_t)(void);
> +
> +extern xsm_initcall_t __xsm_initcall_start[], __xsm_initcall_end[];
> +
> +#define xsm_initcall(fn) \
> + static xsm_initcall_t __initcall_##fn \
> + __attribute_used__ __attribute__((__section__(".xsm_initcall.init"))) =
> fn
> +
> +struct xsm_operations {
> + void (*security_domaininfo) (struct domain *d, dom0_getdomaininfo_t
> *info);
> + int (*setvcpucontext) (struct domain *d);
> + int (*pausedomain) (struct domain *d);
> + int (*unpausedomain) (struct domain *d);
> + int (*createdomain) (dom0_op_t *op);
> + void (*createdomain_post) (struct domain *d, dom0_op_t *op);
> + void (*createdomain_fail) (dom0_op_t *op);
> + int (*max_vcpus) (struct domain *d);
> + int (*destroydomain) (struct domain *d);
> + int (*setvcpuaffinity) (struct domain *d);
> + int (*schedctl) (struct sched_ctl_cmd *cmd);
> + int (*adjustdom) (struct sched_adjdom_cmd *cmd);
> + int (*getdomaininfo) (struct domain *d);
> + int (*getvcpucontext) (struct domain *d);
> + int (*getvcpuinfo) (struct domain *d);
> + int (*settime) (void);
> + int (*tbufcontrol) (void);
> + int (*readconsole) (uint32_t clear);
> + int (*sched_id) (void);
> + int (*setdomainmaxmem) (struct domain *d);
> + int (*setdomainhandle) (struct domain *d);
> + int (*setdebugging) (struct domain *d);
> + int (*irq_permission) (struct domain *d, uint8_t pirq, uint8_t access);
> + int (*iomem_permission) (struct domain *d, unsigned long mfn, uint8_t
> access);
> + int (*perfcontrol) (void);
> +
> + int (*msr) (uint32_t);
Platform specific code might want ifdefs, or perhaps a just platform
specific set of ops.
> + int (*shadow_control) (struct domain *d, uint32_t op);
> + int (*memtype) (uint32_t access);
> + int (*microcode) (void);
> + int (*ioport_permission) (struct domain *d, uint32_t ioport, uint8_t
> access);
> + int (*physinfo) (void);
> + int (*getpageframeinfo) (unsigned long mfn);
> + int (*getmemlist) (struct domain *d);
> + int (*platform_quirk) (uint32_t);
> + int (*physmemmap) (void);
> + int (*hypercall_init) (struct domain *d);
> +
> + int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t
> id2);
> + int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
> + struct domain *d2, struct evtchn *chn2);
> + int (*evtchn_virq) (struct domain *d, struct evtchn *chn, int virq, int
> vcpu);
> + int (*evtchn_ipi) (struct domain *d, struct evtchn *chn, int vcpu);
> + int (*evtchn_pirq) (struct domain *d, struct evtchn *chn, int pirq);
> + int (*evtchn_close) (struct domain *d, struct evtchn *chn);
> + int (*evtchn_send) (struct domain *d, struct evtchn *chn);
> + int (*evtchn_status) (struct domain *d, struct evtchn *chn);
> + int (*evtchn_vcpu) (struct domain *d, struct evtchn *chn, unsigned int
> vcpu);
> + int (*evtchn_unmask) (struct domain *d, struct evtchn *chn);
> + int (*evtchn_init) (struct domain *d, struct evtchn *chn);
> +
> + int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t
> flags);
> + int (*grant_unmapref) (struct domain *d1, struct domain *d2);
> + int (*grant_setup) (struct domain *d1, struct domain *d2);
> + int (*grant_transfer) (struct domain *d1, struct domain *d2);
> +
> + int (*alloc_security_domain) (struct domain *d);
> + void (*free_security_domain) (struct domain *d);
> + int (*alloc_security_evtchn) (struct evtchn *chn);
> + void (*free_security_evtchn) (struct evtchn *chn);
Heh, well, that's as good as a list ;-)
> + int (*mmu_normal_update) (struct domain *d, intpte_t fpte);
> +
> + long (*__do_xsm_op) (GUEST_HANDLE(xsm_op_t) op);
We very intentionally did not do this in LSM (or more to the point,
we did and it was soundly rejected). It's a free form way to extend the
hypercall interface, which in Linux is frowned upon. Of course, you don't
have the various selinuxfs, /proc/<pid>/attr type of interfaces in the
hypervisor, but it's worth considering if there are other possibilities
(32/64-bit compat is an example of something which is easily lost when
pushing the hypercall interface down a layer into the module).
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/xsm/Makefile
> --- /dev/null Thu Jan 1 00:00:00 1970 +0000
> +++ b/xen/xsm/Makefile Thu Aug 31 17:14:49 2006 -0400
> @@ -0,0 +1,3 @@
> +obj-y += xsm_core.o
> +obj-y += xsm_policy.o
> +obj-y += dummy.o
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/xsm/dummy.c
> --- /dev/null Thu Jan 1 00:00:00 1970 +0000
> +++ b/xen/xsm/dummy.c Thu Aug 31 17:14:49 2006 -0400
> @@ -0,0 +1,392 @@
> +#include <xen/sched.h>
> +#include <xsm/xsm.h>
> +
> +#ifdef XSM_ENABLE
Can you just conditionally compile in this file using the above Makefile?
> diff -r d82a4c4d04d4 -r a24b5a5f5f5b xen/xsm/xsm_core.c
> --- /dev/null Thu Jan 1 00:00:00 1970 +0000
> +++ b/xen/xsm/xsm_core.c Thu Aug 31 17:14:49 2006 -0400
<snip>
> +#ifdef XSM_ENABLE
> +#endif
> +
> +long do_xsm_op (GUEST_HANDLE(xsm_op_t) op)
> +{
> + return __do_xsm_op(op);
> +}
Linux has the cond_syscall() macro, should be enough to do this
if you can't find a better way to do security module specifc
calls.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|