ia64/xen-unstable
changeset 8977:f84d5cdd9895
Clean up segment selector fixup and validation.
Signed-off-by: Keir Fraser <keir@xensource.com>
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)