bbd911c
From: Jan Beulich <jbeulich@suse.com>
bbd911c
Subject: x86emul: fix huge bit offset handling
bbd911c
bbd911c
We must never chop off the high 32 bits.
bbd911c
bbd911c
This is XSA-195.
bbd911c
bbd911c
Reported-by: George Dunlap <george.dunlap@citrix.com>
bbd911c
Signed-off-by: Jan Beulich <jbeulich@suse.com>
bbd911c
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
bbd911c
bbd911c
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
bbd911c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
bbd911c
@@ -2549,6 +2549,12 @@ x86_emulate(
bbd911c
         else
bbd911c
         {
bbd911c
             /*
bbd911c
+             * Instructions such as bt can reference an arbitrary offset from
bbd911c
+             * their memory operand, but the instruction doing the actual
bbd911c
+             * emulation needs the appropriate op_bytes read from memory.
bbd911c
+             * Adjust both the source register and memory operand to make an
bbd911c
+             * equivalent instruction.
bbd911c
+             *
bbd911c
              * EA       += BitOffset DIV op_bytes*8
bbd911c
              * BitOffset = BitOffset MOD op_bytes*8
bbd911c
              * DIV truncates towards negative infinity.
bbd911c
@@ -2560,14 +2566,15 @@ x86_emulate(
bbd911c
                 src.val = (int32_t)src.val;
bbd911c
             if ( (long)src.val < 0 )
bbd911c
             {
bbd911c
-                unsigned long byte_offset;
bbd911c
-                byte_offset = op_bytes + (((-src.val-1) >> 3) & ~(op_bytes-1));
bbd911c
+                unsigned long byte_offset =
bbd911c
+                    op_bytes + (((-src.val - 1) >> 3) & ~(op_bytes - 1L));
bbd911c
+
bbd911c
                 ea.mem.off -= byte_offset;
bbd911c
                 src.val = (byte_offset << 3) + src.val;
bbd911c
             }
bbd911c
             else
bbd911c
             {
bbd911c
-                ea.mem.off += (src.val >> 3) & ~(op_bytes - 1);
bbd911c
+                ea.mem.off += (src.val >> 3) & ~(op_bytes - 1L);
bbd911c
                 src.val &= (op_bytes << 3) - 1;
bbd911c
             }
bbd911c
         }