From 93aa42b85ae0084ba7b749d0e990c94fbf0c17e3 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 22 Nov 2016 13:45:44 +0100 Subject: [PATCH] x86/HVM: don't load LDTR with VM86 mode attrs during task switch Just like TR, LDTR is purely a protected mode facility and hence needs to be loaded accordingly. Also move its loading to where it architecurally belongs. This is CVE-2016-9382 / XSA-192. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper Tested-by: Andrew Cooper --- xen/arch/x86/hvm/hvm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index deb1783848..1f9666a533 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2732,17 +2732,16 @@ static void hvm_unmap_entry(void *p) } static int hvm_load_segment_selector( - enum x86_segment seg, uint16_t sel) + enum x86_segment seg, uint16_t sel, unsigned int eflags) { struct segment_register desctab, cs, segr; struct desc_struct *pdesc, desc; u8 dpl, rpl, cpl; bool_t writable; int fault_type = TRAP_invalid_tss; - struct cpu_user_regs *regs = guest_cpu_user_regs(); struct vcpu *v = current; - if ( regs->eflags & X86_EFLAGS_VM ) + if ( eflags & X86_EFLAGS_VM ) { segr.sel = sel; segr.base = (uint32_t)sel << 4; @@ -2994,6 +2993,8 @@ void hvm_task_switch( if ( rc != HVMCOPY_okay ) goto out; + if ( hvm_load_segment_selector(x86_seg_ldtr, tss.ldt, 0) ) + goto out; if ( hvm_set_cr3(tss.cr3, 1) ) goto out; @@ -3016,13 +3017,12 @@ void hvm_task_switch( } exn_raised = 0; - if ( hvm_load_segment_selector(x86_seg_ldtr, tss.ldt) || - hvm_load_segment_selector(x86_seg_es, tss.es) || - hvm_load_segment_selector(x86_seg_cs, tss.cs) || - hvm_load_segment_selector(x86_seg_ss, tss.ss) || - hvm_load_segment_selector(x86_seg_ds, tss.ds) || - hvm_load_segment_selector(x86_seg_fs, tss.fs) || - hvm_load_segment_selector(x86_seg_gs, tss.gs) ) + if ( hvm_load_segment_selector(x86_seg_es, tss.es, tss.eflags) || + hvm_load_segment_selector(x86_seg_cs, tss.cs, tss.eflags) || + hvm_load_segment_selector(x86_seg_ss, tss.ss, tss.eflags) || + hvm_load_segment_selector(x86_seg_ds, tss.ds, tss.eflags) || + hvm_load_segment_selector(x86_seg_fs, tss.fs, tss.eflags) || + hvm_load_segment_selector(x86_seg_gs, tss.gs, tss.eflags) ) exn_raised = 1; rc = hvm_copy_to_guest_virt( -- 2.30.2