All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86_emulate: Always truncate %eip out of long mode
@ 2015-12-10 20:03 Andrew Cooper
  2015-12-11 10:47 ` Jan Beulich
  2015-12-15  8:53 ` Jan Beulich
  0 siblings, 2 replies; 7+ messages in thread
From: Andrew Cooper @ 2015-12-10 20:03 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich

_regs.eip needs to be truncated after having size added to it, or bad
situations can occur. e.g. emulating an instruction which crosses the 4GB
boundary causes _regs.eip to become invalid (have some of the upper 32 bits
set), and fail vmentry checks when returning back to the guest.

The comment /* real hardware doesn't truncate */ seems to appear in c/s
ddef8e16 "Tweak x86 emulator interface." without any justification.

I have not been able to find any information to prove or disprove the claim,
but emulating oneself into a vmentry failure is definitely the wrong thing to
do.

Trucate the instruction pointer at 32 or 16 bits, according to %cs.D.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>

v2: Use def_ad_bytes, to allow truncating to 16 bits for a 16bit code segment.
---
 xen/arch/x86/x86_emulate/x86_emulate.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index f1454ce..03e7aab 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -570,8 +570,10 @@ do{ asm volatile (                                                      \
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch_bytes(_size)                                         \
 ({ unsigned long _x = 0, _eip = _regs.eip;                              \
-   if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \
-   _regs.eip += (_size); /* real hardware doesn't truncate */           \
+   _regs.eip += (_size);                                                \
+   if ( !mode_64bit() ) { /* Truncate eip to def_ad_bytes (2 or 4). */  \
+       _eip      &= ~((1UL << (def_ad_bytes * 8)) - 1);                 \
+       _regs.eip &= ~((1UL << (def_ad_bytes * 8)) - 1); };              \
    generate_exception_if((uint8_t)(_regs.eip -                          \
                                    ctxt->regs->eip) > MAX_INST_LEN,     \
                          EXC_GP, 0);                                    \
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-01-06 16:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-10 20:03 [PATCH] x86_emulate: Always truncate %eip out of long mode Andrew Cooper
2015-12-11 10:47 ` Jan Beulich
2015-12-11 11:12   ` Andrew Cooper
2015-12-11 13:28     ` Jan Beulich
2015-12-15  8:53 ` Jan Beulich
2016-01-06 15:44   ` Jan Beulich
2016-01-06 16:09     ` Andrew Cooper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.