From: Jan Beulich Date: Tue, 22 Nov 2016 12:49:06 +0000 (+0100) Subject: x86emul: fix huge bit offset handling X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~85 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=1c6c2d60d205f71ede0fbbd9047e459112f576db;p=xen.git x86emul: fix huge bit offset handling We must never chop off the high 32 bits. This is CVE-2016-9383 / XSA-195. Reported-by: George Dunlap Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index f9cdb63426..90add39f70 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2537,6 +2537,12 @@ x86_emulate( else { /* + * Instructions such as bt can reference an arbitrary offset from + * their memory operand, but the instruction doing the actual + * emulation needs the appropriate op_bytes read from memory. + * Adjust both the source register and memory operand to make an + * equivalent instruction. + * * EA += BitOffset DIV op_bytes*8 * BitOffset = BitOffset MOD op_bytes*8 * DIV truncates towards negative infinity. @@ -2548,14 +2554,15 @@ x86_emulate( src.val = (int32_t)src.val; if ( (long)src.val < 0 ) { - unsigned long byte_offset; - byte_offset = op_bytes + (((-src.val-1) >> 3) & ~(op_bytes-1)); + unsigned long byte_offset = + op_bytes + (((-src.val - 1) >> 3) & ~(op_bytes - 1L)); + ea.mem.off -= byte_offset; src.val = (byte_offset << 3) + src.val; } else { - ea.mem.off += (src.val >> 3) & ~(op_bytes - 1); + ea.mem.off += (src.val >> 3) & ~(op_bytes - 1L); src.val &= (op_bytes << 3) - 1; } }