Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
xen.5015
58343dc2-x86-hvm-Fix-the-handling-of-non-presen...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 58343dc2-x86-hvm-Fix-the-handling-of-non-present-segments.patch of Package xen.5015
Subject: x86/hvm: Fix the handling of non-present segments From: Andrew Cooper andrew.cooper3@citrix.com Tue Nov 22 14:27:40 2016 +0100 Date: Tue Nov 22 14:27:40 2016 +0100: Git: 877b7602876b54f2c7c4c19374ee189db6194d73 In 32bit, the data segments may be NULL to indicate that the segment is ineligible for use. In both 32bit and 64bit, the LDT selector may be NULL to indicate that the entire LDT is ineligible for use. However, nothing in Xen actually checks for this condition when performing other segmentation checks. (Note however that limit and writeability checks are correctly performed). Neither Intel nor AMD specify the exact behaviour of loading a NULL segment. Experimentally, AMD zeroes all attributes but leaves the base and limit unmodified. Intel zeroes the base, sets the limit to 0xfffffff and resets the attributes to just .G and .D/B. The use of the segment information in the VMCB/VMCS is equivalent to a native pipeline interacting with the segment cache. The present bit can therefore have a subtly different meaning, and it is now cooked to uniformly indicate whether the segment is usable or not. GDTR and IDTR don't have access rights like the other segments, but for consistency, they are treated as being present so no special casing is needed elsewhere in the segmentation logic. AMD hardware does not consider the present bit for %cs and %tr, and will function as if they were present. They are therefore unconditionally set to present when reading information from the VMCB, to maintain the new meaning of usability. Intel hardware has a separate unusable bit in the VMCS segment attributes. This bit is inverted and stored in the present field, so the hvm code can work with architecturally-common state. This is CVE-2016-9386 / XSA-191. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> master commit: 04beafa8e6c66f5cd814c00e2d2b51cfbc41cb8a master date: 2016-11-22 13:44:50 +0100 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2173,6 +2173,10 @@ int hvm_virtual_to_linear_addr( * COMPATIBILITY MODE: Apply segment checks and add base. */ + /* Segment not valid for use (cooked meaning of .p)? */ + if ( !reg->attr.fields.p ) + return 0; + switch ( access_type ) { case hvm_access_read: @@ -2370,6 +2374,10 @@ static int hvm_load_segment_selector( hvm_get_segment_register( v, (sel & 4) ? x86_seg_ldtr : x86_seg_gdtr, &desctab); + /* Segment not valid for use (cooked meaning of .p)? */ + if ( !desctab.attr.fields.p ) + goto fail; + /* Check against descriptor table limit. */ if ( ((sel & 0xfff8) + 7) > desctab.limit ) goto fail; --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -523,6 +523,7 @@ static void svm_get_segment_register(str { case x86_seg_cs: memcpy(reg, &vmcb->cs, sizeof(*reg)); + reg->attr.fields.p = 1; reg->attr.fields.g = reg->limit > 0xFFFFF; break; case x86_seg_ds: @@ -556,13 +557,16 @@ static void svm_get_segment_register(str case x86_seg_tr: svm_sync_vmcb(v); memcpy(reg, &vmcb->tr, sizeof(*reg)); + reg->attr.fields.p = 1; reg->attr.fields.type |= 0x2; break; case x86_seg_gdtr: memcpy(reg, &vmcb->gdtr, sizeof(*reg)); + reg->attr.bytes = 0x80; break; case x86_seg_idtr: memcpy(reg, &vmcb->idtr, sizeof(*reg)); + reg->attr.bytes = 0x80; break; case x86_seg_ldtr: svm_sync_vmcb(v); --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -774,10 +774,12 @@ void vmx_get_segment_register(struct vcp reg->sel = sel; reg->limit = limit; - reg->attr.bytes = (attr & 0xff) | ((attr >> 4) & 0xf00); - /* Unusable flag is folded into Present flag. */ - if ( attr & (1u<<16) ) - reg->attr.fields.p = 0; + /* + * Fold VT-x representation into Xen's representation. The Present bit is + * unconditionally set to the inverse of unusable. + */ + reg->attr.bytes = + (!(attr & (1u << 16)) << 7) | (attr & 0x7f) | ((attr >> 4) & 0xf00); /* Adjust for virtual 8086 mode */ if ( v->arch.hvm_vmx.vmx_realmode && seg <= x86_seg_tr @@ -857,11 +859,11 @@ static void vmx_set_segment_register(str } } - attr = ((attr & 0xf00) << 4) | (attr & 0xff); - - /* Not-present must mean unusable. */ - if ( !reg->attr.fields.p ) - attr |= (1u << 16); + /* + * Unfold Xen representation into VT-x representation. The unusable bit + * is unconditionally set to the inverse of present. + */ + attr = (!(attr & (1u << 7)) << 16) | ((attr & 0xf00) << 4) | (attr & 0xff); /* VMX has strict consistency requirement for flag G. */ attr |= !!(limit >> 20) << 15; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -1210,6 +1210,10 @@ protmode_load_seg( &desctab, ctxt)) ) return rc; + /* Segment not valid for use (cooked meaning of .p)? */ + if ( !desctab.attr.fields.p ) + goto raise_exn; + /* Check against descriptor table limit. */ if ( ((sel & 0xfff8) + 7) > desctab.limit ) goto raise_exn;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor