[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |