[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] vvmx: fix instruction decode segment limit check


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-unstable <patchbot@xxxxxxx>
  • Date: Mon, 14 May 2012 16:32:05 +0000
  • Delivery-date: Mon, 14 May 2012 16:32:12 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1335358476 -3600
# Node ID 7883b6dea8f82c236ab09ce311c1692dd1d31fc7
# Parent  ed9c557f8a35a6deb7e6df0679f24a2121fd1172
vvmx: fix instruction decode segment limit check

- no limit check for 64-bit mode (and GS: is not special in any way)
- limit check is needed in compatibility mode
- canonical address check should instead be performed for 64-bit mode
- the last accessed byte must be within limits, not the first byte
- past the accessed range
- segment base address should be ignored for 64-bit mode unless FS: or
  GS: is in use

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Tim Deegan <tim@xxxxxxx>
Committed-by: Keir Fraser <keir@xxxxxxx>
---


diff -r ed9c557f8a35 -r 7883b6dea8f8 xen/arch/x86/hvm/vmx/vvmx.c
--- a/xen/arch/x86/hvm/vmx/vvmx.c       Wed Apr 25 13:53:14 2012 +0100
+++ b/xen/arch/x86/hvm/vmx/vvmx.c       Wed Apr 25 13:54:36 2012 +0100
@@ -336,8 +336,17 @@ static int decode_vmx_inst(struct cpu_us
     }
     else
     {
+        bool_t mode_64bit = 0;
+
         decode->type = VMX_INST_MEMREG_TYPE_MEMORY;
-        if ( info.fields.segment > 5 )
+
+        if ( hvm_long_mode_enabled(v) )
+        {
+            hvm_get_segment_register(v, x86_seg_cs, &seg);
+            mode_64bit = seg.attr.fields.l;
+        }
+
+        if ( info.fields.segment > VMX_SREG_GS )
             goto gp_fault;
         hvm_get_segment_register(v, sreg_to_index[info.fields.segment], &seg);
         seg_base = seg.base;
@@ -355,15 +364,20 @@ static int decode_vmx_inst(struct cpu_us
         size = 1 << (info.fields.addr_size + 1);
 
         offset = base + index * scale + disp;
-        if ( (offset > seg.limit || offset + size > seg.limit) &&
-            (!hvm_long_mode_enabled(v) || info.fields.segment == VMX_SREG_GS) )
+        base = !mode_64bit || info.fields.segment >= VMX_SREG_FS ?
+               seg_base + offset : offset;
+        if ( offset + size - 1 < offset ||
+             (mode_64bit ?
+              !is_canonical_address((long)base < 0 ? base :
+                                    base + size - 1) :
+              offset + size - 1 > seg.limit) )
             goto gp_fault;
 
         if ( poperandS != NULL &&
-             hvm_copy_from_guest_virt(poperandS, seg_base + offset, size, 0)
+             hvm_copy_from_guest_virt(poperandS, base, size, 0)
                   != HVMCOPY_okay )
             return X86EMUL_EXCEPTION;
-        decode->mem = seg_base + offset;
+        decode->mem = base;
         decode->len = size;
     }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.