[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [Xense-devel][RFC][PATCH][1/4] Xen Security Modules: XSM



* 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.