# 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
|