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

[Xen-changelog] Clean up segment selector fixup and validation.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID f84d5cdd9895206af83fbe7798f026b140e7b68f
# Parent  4f4625f805288891106421ea185a02f95dd9c530
Clean up segment selector fixup and validation.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 4f4625f80528 -r f84d5cdd9895 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Feb 23 10:59:27 2006
+++ b/xen/arch/x86/domain.c     Thu Feb 23 13:43:45 2006
@@ -349,27 +349,19 @@
     unsigned long phys_basetab = INVALID_MFN;
     int i, rc;
 
-    /*
-     * This is sufficient! If the descriptor DPL differs from CS RPL then we'll
-     * #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically.
-     * If SS RPL or DPL differs from CS RPL then we'll #GP.
-     */
     if ( !(c->flags & VGCF_HVM_GUEST) )
     {
-        if ( !VALID_STACKSEL(c->user_regs.ss) ||
-             !VALID_STACKSEL(c->kernel_ss) ||
-             !VALID_CODESEL(c->user_regs.cs) )
-            return -EINVAL;
+        fixup_guest_selector(c->user_regs.ss);
+        fixup_guest_selector(c->kernel_ss);
+        fixup_guest_selector(c->user_regs.cs);
 
 #ifdef __i386__
-        if ( !VALID_CODESEL(c->event_callback_cs) ||
-             !VALID_CODESEL(c->failsafe_callback_cs) )
-            return -EINVAL;
+        fixup_guest_selector(c->event_callback_cs);
+        fixup_guest_selector(c->failsafe_callback_cs);
 #endif
 
         for ( i = 0; i < 256; i++ )
-            if ( !VALID_CODESEL(c->trap_ctxt[i].cs) )
-                return -EINVAL;
+            fixup_guest_selector(c->trap_ctxt[i].cs);
     }
     else if ( !hvm_enabled )
       return -EINVAL;
@@ -383,6 +375,7 @@
         v->arch.flags |= TF_kernel_mode;
 
     memcpy(&v->arch.guest_context, c, sizeof(*c));
+    init_int80_direct_trap(v);
 
     if ( !(c->flags & VGCF_HVM_GUEST) )
     {
diff -r 4f4625f80528 -r f84d5cdd9895 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Feb 23 10:59:27 2006
+++ b/xen/arch/x86/traps.c      Thu Feb 23 13:43:45 2006
@@ -1430,11 +1430,7 @@
         if ( cur.address == 0 )
             break;
 
-        if ( !VALID_CODESEL(cur.cs) )
-        {
-            rc = -EPERM;
-            break;
-        }
+        fixup_guest_selector(cur.cs);
 
         memcpy(&dst[cur.vector], &cur, sizeof(cur));
 
diff -r 4f4625f80528 -r f84d5cdd9895 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Thu Feb 23 10:59:27 2006
+++ b/xen/arch/x86/x86_32/mm.c  Thu Feb 23 13:43:45 2006
@@ -223,8 +223,7 @@
     int nr = smp_processor_id();
     struct tss_struct *t = &init_tss[nr];
 
-    if ( !VALID_STACKSEL(ss) )
-        return -EPERM;
+    fixup_guest_selector(ss);
 
     current->arch.guest_context.kernel_ss = ss;
     current->arch.guest_context.kernel_sp = esp;
@@ -239,7 +238,7 @@
 {
     unsigned long base, limit;
     u32 a = d->a, b = d->b;
-    u16 cs = a>>16;
+    u16 cs;
 
     /* A not-present descriptor will always fault, so is safe. */
     if ( !(b & _SEGMENT_P) ) 
@@ -272,17 +271,12 @@
         if ( (b & _SEGMENT_TYPE) != 0xc00 )
             goto bad;
 
-        /* Can't allow far jump to a Xen-private segment. */
-        if ( !VALID_CODESEL(cs) )
+        /* Validate and fix up the target code selector. */
+        cs = a >> 16;
+        fixup_guest_selector(cs);
+        if ( !guest_gate_selector_okay(cs) )
             goto bad;
-
-        /*
-         * VALID_CODESEL might have fixed up the RPL for us. So be sure to
-         * update the descriptor.
-         *
-         */
-        d->a &= 0x0000ffff;
-        d->a |= cs<<16;
+        a = d->a = (d->a & 0xffffU) | (cs << 16);
 
         /* Reserved bits must be zero. */
         if ( (b & 0xe0) != 0 )
diff -r 4f4625f80528 -r f84d5cdd9895 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Thu Feb 23 10:59:27 2006
+++ b/xen/arch/x86/x86_32/traps.c       Thu Feb 23 13:43:45 2006
@@ -254,10 +254,14 @@
 
     /*
      * We can't virtualise interrupt gates, as there's no way to get
-     * the CPU to automatically clear the events_mask variable.
-     */
-    if ( TI_GET_IF(ti) )
+     * the CPU to automatically clear the events_mask variable. Also we
+     * must ensure that the CS is safe to poke into an interrupt gate.
+     */
+    if ( TI_GET_IF(ti) || !guest_gate_selector_okay(ti->cs) )
+    {
+        v->arch.int80_desc.a = v->arch.int80_desc.b = 0;
         return;
+    }
 
     v->arch.int80_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
     v->arch.int80_desc.b =
@@ -274,8 +278,8 @@
 {
     struct vcpu *d = current;
 
-    if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
-        return -EPERM;
+    fixup_guest_selector(event_selector);
+    fixup_guest_selector(failsafe_selector);
 
     d->arch.guest_context.event_callback_cs     = event_selector;
     d->arch.guest_context.event_callback_eip    = event_address;
diff -r 4f4625f80528 -r f84d5cdd9895 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Thu Feb 23 10:59:27 2006
+++ b/xen/arch/x86/x86_64/mm.c  Thu Feb 23 13:43:45 2006
@@ -292,7 +292,7 @@
 int check_descriptor(struct desc_struct *d)
 {
     u32 a = d->a, b = d->b;
-    u16 cs = a>>16;
+    u16 cs;
 
     /* A not-present descriptor will always fault, so is safe. */
     if ( !(b & _SEGMENT_P) ) 
@@ -314,17 +314,12 @@
     if ( (b & _SEGMENT_TYPE) != 0xc00 )
         goto bad;
 
-    /* Can't allow far jump to a Xen-private segment. */
-    if ( !VALID_CODESEL(cs) )
+    /* Validate and fix up the target code selector. */
+    cs = a >> 16;
+    fixup_guest_selector(cs);
+    if ( !guest_gate_selector_okay(cs) )
         goto bad;
-
-    /*
-     * VALID_CODESEL might have fixed up the RPL for us. So be sure to
-     * update the descriptor.
-     *
-     */
-    d->a &= 0x0000ffff;
-    d->a |= cs<<16;
+    a = d->a = (d->a & 0xffffU) | (cs << 16);
 
     /* Reserved bits must be zero. */
     if ( (b & 0xe0) != 0 )
diff -r 4f4625f80528 -r f84d5cdd9895 xen/common/elf.c
--- a/xen/common/elf.c  Thu Feb 23 10:59:27 2006
+++ b/xen/common/elf.c  Thu Feb 23 13:43:45 2006
@@ -61,7 +61,6 @@
             continue;
 
         guestinfo = elfbase + shdr->sh_offset;
-        printk("Xen-ELF header found: '%s'\n", guestinfo);
 
         if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
              (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
diff -r 4f4625f80528 -r f84d5cdd9895 xen/include/asm-x86/desc.h
--- a/xen/include/asm-x86/desc.h        Thu Feb 23 10:59:27 2006
+++ b/xen/include/asm-x86/desc.h        Thu Feb 23 13:43:45 2006
@@ -26,23 +26,28 @@
 #define GUEST_KERNEL_RPL 1
 #endif
 
+/* Fix up the RPL of a guest segment selector. */
+#define fixup_guest_selector(sel)                               \
+    ((sel) = (((sel) & 3) >= GUEST_KERNEL_RPL) ? (sel) :        \
+     (((sel) & ~3) | GUEST_KERNEL_RPL))
+
 /*
- * Guest OS must provide its own code selectors, or use the one we provide. Any
- * LDT selector value is okay. Note that checking only the RPL is insufficient:
- * if the selector is poked into an interrupt, trap or call gate then the RPL
- * is ignored when the gate is accessed.
+ * We need this function because enforcing the correct guest kernel RPL is
+ * unsufficient if the selector is poked into an interrupt, trap or call gate.
+ * The selector RPL is ignored when a gate is accessed. We must therefore make
+ * sure that the selector does not reference a Xen-private segment.
+ * 
+ * Note that selectors used only by IRET do not need to be checked. If the
+ * descriptor DPL fiffers from CS RPL then we'll #GP.
+ * 
+ * Stack and data selectors do not need to be checked. If DS, ES, FS, GS are
+ * DPL < CPL then they'll be cleared automatically. If SS RPL or DPL differs
+ * from CS RPL then we'll #GP.
  */
-#define VALID_SEL(_s)                                                      \
-    (((((_s)>>3) < FIRST_RESERVED_GDT_ENTRY) || ((_s)&4)) &&               \
-     (((_s)&3) == GUEST_KERNEL_RPL))
-#define VALID_CODESEL(_s) ({                                               \
-    if ( ((_s) & 3) == 0 )                                                 \
-        (_s) |= GUEST_KERNEL_RPL;                                          \
-    (_s) == FLAT_KERNEL_CS || VALID_SEL(_s); })
-#define VALID_STACKSEL(_s) ({                                              \
-    if ( ((_s) & 3) == 0 )                                                 \
-        (_s) |= GUEST_KERNEL_RPL;                                          \
-    (_s) == FLAT_KERNEL_SS || VALID_SEL(_s); })
+#define guest_gate_selector_okay(sel)                                   \
+    ((((sel)>>3) < FIRST_RESERVED_GDT_ENTRY) || /* Guest seg? */        \
+     ((sel) == FLAT_KERNEL_CS) ||               /* Xen default seg? */  \
+     ((sel) & 4))                               /* LDT seg? */
 
 /* These are bitmasks for the high 32 bits of a descriptor table entry. */
 #define _SEGMENT_TYPE    (15<< 8)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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