ia64/xen-unstable

changeset 8977:f84d5cdd9895

Clean up segment selector fixup and validation.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 23 14:43:45 2006 +0100 (2006-02-23)
parents 4f4625f80528
children 066ac36725f3
files xen/arch/x86/domain.c xen/arch/x86/traps.c xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/mm.c xen/common/elf.c xen/include/asm-x86/desc.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Thu Feb 23 11:59:27 2006 +0100
     1.2 +++ b/xen/arch/x86/domain.c	Thu Feb 23 14:43:45 2006 +0100
     1.3 @@ -349,27 +349,19 @@ int arch_set_info_guest(
     1.4      unsigned long phys_basetab = INVALID_MFN;
     1.5      int i, rc;
     1.6  
     1.7 -    /*
     1.8 -     * This is sufficient! If the descriptor DPL differs from CS RPL then we'll
     1.9 -     * #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically.
    1.10 -     * If SS RPL or DPL differs from CS RPL then we'll #GP.
    1.11 -     */
    1.12      if ( !(c->flags & VGCF_HVM_GUEST) )
    1.13      {
    1.14 -        if ( !VALID_STACKSEL(c->user_regs.ss) ||
    1.15 -             !VALID_STACKSEL(c->kernel_ss) ||
    1.16 -             !VALID_CODESEL(c->user_regs.cs) )
    1.17 -            return -EINVAL;
    1.18 +        fixup_guest_selector(c->user_regs.ss);
    1.19 +        fixup_guest_selector(c->kernel_ss);
    1.20 +        fixup_guest_selector(c->user_regs.cs);
    1.21  
    1.22  #ifdef __i386__
    1.23 -        if ( !VALID_CODESEL(c->event_callback_cs) ||
    1.24 -             !VALID_CODESEL(c->failsafe_callback_cs) )
    1.25 -            return -EINVAL;
    1.26 +        fixup_guest_selector(c->event_callback_cs);
    1.27 +        fixup_guest_selector(c->failsafe_callback_cs);
    1.28  #endif
    1.29  
    1.30          for ( i = 0; i < 256; i++ )
    1.31 -            if ( !VALID_CODESEL(c->trap_ctxt[i].cs) )
    1.32 -                return -EINVAL;
    1.33 +            fixup_guest_selector(c->trap_ctxt[i].cs);
    1.34      }
    1.35      else if ( !hvm_enabled )
    1.36        return -EINVAL;
    1.37 @@ -383,6 +375,7 @@ int arch_set_info_guest(
    1.38          v->arch.flags |= TF_kernel_mode;
    1.39  
    1.40      memcpy(&v->arch.guest_context, c, sizeof(*c));
    1.41 +    init_int80_direct_trap(v);
    1.42  
    1.43      if ( !(c->flags & VGCF_HVM_GUEST) )
    1.44      {
     2.1 --- a/xen/arch/x86/traps.c	Thu Feb 23 11:59:27 2006 +0100
     2.2 +++ b/xen/arch/x86/traps.c	Thu Feb 23 14:43:45 2006 +0100
     2.3 @@ -1430,11 +1430,7 @@ long do_set_trap_table(struct trap_info 
     2.4          if ( cur.address == 0 )
     2.5              break;
     2.6  
     2.7 -        if ( !VALID_CODESEL(cur.cs) )
     2.8 -        {
     2.9 -            rc = -EPERM;
    2.10 -            break;
    2.11 -        }
    2.12 +        fixup_guest_selector(cur.cs);
    2.13  
    2.14          memcpy(&dst[cur.vector], &cur, sizeof(cur));
    2.15  
     3.1 --- a/xen/arch/x86/x86_32/mm.c	Thu Feb 23 11:59:27 2006 +0100
     3.2 +++ b/xen/arch/x86/x86_32/mm.c	Thu Feb 23 14:43:45 2006 +0100
     3.3 @@ -223,8 +223,7 @@ long do_stack_switch(unsigned long ss, u
     3.4      int nr = smp_processor_id();
     3.5      struct tss_struct *t = &init_tss[nr];
     3.6  
     3.7 -    if ( !VALID_STACKSEL(ss) )
     3.8 -        return -EPERM;
     3.9 +    fixup_guest_selector(ss);
    3.10  
    3.11      current->arch.guest_context.kernel_ss = ss;
    3.12      current->arch.guest_context.kernel_sp = esp;
    3.13 @@ -239,7 +238,7 @@ int check_descriptor(struct desc_struct 
    3.14  {
    3.15      unsigned long base, limit;
    3.16      u32 a = d->a, b = d->b;
    3.17 -    u16 cs = a>>16;
    3.18 +    u16 cs;
    3.19  
    3.20      /* A not-present descriptor will always fault, so is safe. */
    3.21      if ( !(b & _SEGMENT_P) ) 
    3.22 @@ -272,17 +271,12 @@ int check_descriptor(struct desc_struct 
    3.23          if ( (b & _SEGMENT_TYPE) != 0xc00 )
    3.24              goto bad;
    3.25  
    3.26 -        /* Can't allow far jump to a Xen-private segment. */
    3.27 -        if ( !VALID_CODESEL(cs) )
    3.28 +        /* Validate and fix up the target code selector. */
    3.29 +        cs = a >> 16;
    3.30 +        fixup_guest_selector(cs);
    3.31 +        if ( !guest_gate_selector_okay(cs) )
    3.32              goto bad;
    3.33 -
    3.34 -        /*
    3.35 -         * VALID_CODESEL might have fixed up the RPL for us. So be sure to
    3.36 -         * update the descriptor.
    3.37 -         *
    3.38 -         */
    3.39 -        d->a &= 0x0000ffff;
    3.40 -        d->a |= cs<<16;
    3.41 +        a = d->a = (d->a & 0xffffU) | (cs << 16);
    3.42  
    3.43          /* Reserved bits must be zero. */
    3.44          if ( (b & 0xe0) != 0 )
     4.1 --- a/xen/arch/x86/x86_32/traps.c	Thu Feb 23 11:59:27 2006 +0100
     4.2 +++ b/xen/arch/x86/x86_32/traps.c	Thu Feb 23 14:43:45 2006 +0100
     4.3 @@ -254,10 +254,14 @@ void init_int80_direct_trap(struct vcpu 
     4.4  
     4.5      /*
     4.6       * We can't virtualise interrupt gates, as there's no way to get
     4.7 -     * the CPU to automatically clear the events_mask variable.
     4.8 +     * the CPU to automatically clear the events_mask variable. Also we
     4.9 +     * must ensure that the CS is safe to poke into an interrupt gate.
    4.10       */
    4.11 -    if ( TI_GET_IF(ti) )
    4.12 +    if ( TI_GET_IF(ti) || !guest_gate_selector_okay(ti->cs) )
    4.13 +    {
    4.14 +        v->arch.int80_desc.a = v->arch.int80_desc.b = 0;
    4.15          return;
    4.16 +    }
    4.17  
    4.18      v->arch.int80_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
    4.19      v->arch.int80_desc.b =
    4.20 @@ -274,8 +278,8 @@ long do_set_callbacks(unsigned long even
    4.21  {
    4.22      struct vcpu *d = current;
    4.23  
    4.24 -    if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
    4.25 -        return -EPERM;
    4.26 +    fixup_guest_selector(event_selector);
    4.27 +    fixup_guest_selector(failsafe_selector);
    4.28  
    4.29      d->arch.guest_context.event_callback_cs     = event_selector;
    4.30      d->arch.guest_context.event_callback_eip    = event_address;
     5.1 --- a/xen/arch/x86/x86_64/mm.c	Thu Feb 23 11:59:27 2006 +0100
     5.2 +++ b/xen/arch/x86/x86_64/mm.c	Thu Feb 23 14:43:45 2006 +0100
     5.3 @@ -292,7 +292,7 @@ long do_set_segment_base(unsigned int wh
     5.4  int check_descriptor(struct desc_struct *d)
     5.5  {
     5.6      u32 a = d->a, b = d->b;
     5.7 -    u16 cs = a>>16;
     5.8 +    u16 cs;
     5.9  
    5.10      /* A not-present descriptor will always fault, so is safe. */
    5.11      if ( !(b & _SEGMENT_P) ) 
    5.12 @@ -314,17 +314,12 @@ int check_descriptor(struct desc_struct 
    5.13      if ( (b & _SEGMENT_TYPE) != 0xc00 )
    5.14          goto bad;
    5.15  
    5.16 -    /* Can't allow far jump to a Xen-private segment. */
    5.17 -    if ( !VALID_CODESEL(cs) )
    5.18 +    /* Validate and fix up the target code selector. */
    5.19 +    cs = a >> 16;
    5.20 +    fixup_guest_selector(cs);
    5.21 +    if ( !guest_gate_selector_okay(cs) )
    5.22          goto bad;
    5.23 -
    5.24 -    /*
    5.25 -     * VALID_CODESEL might have fixed up the RPL for us. So be sure to
    5.26 -     * update the descriptor.
    5.27 -     *
    5.28 -     */
    5.29 -    d->a &= 0x0000ffff;
    5.30 -    d->a |= cs<<16;
    5.31 +    a = d->a = (d->a & 0xffffU) | (cs << 16);
    5.32  
    5.33      /* Reserved bits must be zero. */
    5.34      if ( (b & 0xe0) != 0 )
     6.1 --- a/xen/common/elf.c	Thu Feb 23 11:59:27 2006 +0100
     6.2 +++ b/xen/common/elf.c	Thu Feb 23 14:43:45 2006 +0100
     6.3 @@ -61,7 +61,6 @@ int parseelfimage(struct domain_setup_in
     6.4              continue;
     6.5  
     6.6          guestinfo = elfbase + shdr->sh_offset;
     6.7 -        printk("Xen-ELF header found: '%s'\n", guestinfo);
     6.8  
     6.9          if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
    6.10               (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
     7.1 --- a/xen/include/asm-x86/desc.h	Thu Feb 23 11:59:27 2006 +0100
     7.2 +++ b/xen/include/asm-x86/desc.h	Thu Feb 23 14:43:45 2006 +0100
     7.3 @@ -26,23 +26,28 @@
     7.4  #define GUEST_KERNEL_RPL 1
     7.5  #endif
     7.6  
     7.7 +/* Fix up the RPL of a guest segment selector. */
     7.8 +#define fixup_guest_selector(sel)                               \
     7.9 +    ((sel) = (((sel) & 3) >= GUEST_KERNEL_RPL) ? (sel) :        \
    7.10 +     (((sel) & ~3) | GUEST_KERNEL_RPL))
    7.11 +
    7.12  /*
    7.13 - * Guest OS must provide its own code selectors, or use the one we provide. Any
    7.14 - * LDT selector value is okay. Note that checking only the RPL is insufficient:
    7.15 - * if the selector is poked into an interrupt, trap or call gate then the RPL
    7.16 - * is ignored when the gate is accessed.
    7.17 + * We need this function because enforcing the correct guest kernel RPL is
    7.18 + * unsufficient if the selector is poked into an interrupt, trap or call gate.
    7.19 + * The selector RPL is ignored when a gate is accessed. We must therefore make
    7.20 + * sure that the selector does not reference a Xen-private segment.
    7.21 + * 
    7.22 + * Note that selectors used only by IRET do not need to be checked. If the
    7.23 + * descriptor DPL fiffers from CS RPL then we'll #GP.
    7.24 + * 
    7.25 + * Stack and data selectors do not need to be checked. If DS, ES, FS, GS are
    7.26 + * DPL < CPL then they'll be cleared automatically. If SS RPL or DPL differs
    7.27 + * from CS RPL then we'll #GP.
    7.28   */
    7.29 -#define VALID_SEL(_s)                                                      \
    7.30 -    (((((_s)>>3) < FIRST_RESERVED_GDT_ENTRY) || ((_s)&4)) &&               \
    7.31 -     (((_s)&3) == GUEST_KERNEL_RPL))
    7.32 -#define VALID_CODESEL(_s) ({                                               \
    7.33 -    if ( ((_s) & 3) == 0 )                                                 \
    7.34 -        (_s) |= GUEST_KERNEL_RPL;                                          \
    7.35 -    (_s) == FLAT_KERNEL_CS || VALID_SEL(_s); })
    7.36 -#define VALID_STACKSEL(_s) ({                                              \
    7.37 -    if ( ((_s) & 3) == 0 )                                                 \
    7.38 -        (_s) |= GUEST_KERNEL_RPL;                                          \
    7.39 -    (_s) == FLAT_KERNEL_SS || VALID_SEL(_s); })
    7.40 +#define guest_gate_selector_okay(sel)                                   \
    7.41 +    ((((sel)>>3) < FIRST_RESERVED_GDT_ENTRY) || /* Guest seg? */        \
    7.42 +     ((sel) == FLAT_KERNEL_CS) ||               /* Xen default seg? */  \
    7.43 +     ((sel) & 4))                               /* LDT seg? */
    7.44  
    7.45  /* These are bitmasks for the high 32 bits of a descriptor table entry. */
    7.46  #define _SEGMENT_TYPE    (15<< 8)