x86emul: correct and extend IDT entry checks

In order to pre-determine whether a fault will occur upon software
interrupt injection, it is not sufficient to just check P and DPL. Do
at least all the checks on the IDT entry itself, and in particular do
the #NP check last. The checks for the new CS (and perhaps SS) are left
out for now, though.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citirix.com>
This commit is contained in:
Jan Beulich committed 2016-12-07 15:39:03 +01:00
1 parent 216c297656
commit b853489598
1 file changed
+26 -4
+26 -4
View File
@@ -1663,7 +1663,7 @@ static int inject_swint(enum x86_swint_type type,
if ( !in_realmode(ctxt, ops) )
{
unsigned int idte_size, idte_offset;
struct { uint32_t a, b, c, d; } idte;
struct { uint32_t a, b, c, d; } idte = {};
int lm = in_longmode(ctxt, ops);
if ( lm < 0 )
@@ -1708,12 +1708,27 @@ static int inject_swint(enum x86_swint_type type,
return rc;
}
/* Is this entry present? */
if ( !(idte.b & (1u << 15)) )
/* This must be an interrupt, trap, or task gate. */
#ifdef __XEN__
switch ( (idte.b >> 8) & 0x1f )
{
fault_type = EXC_NP;
case SYS_DESC_irq_gate:
case SYS_DESC_trap_gate:
break;
case SYS_DESC_irq_gate16:
case SYS_DESC_trap_gate16:
case SYS_DESC_task_gate:
if ( !lm )
break;
/* fall through */
default:
goto raise_exn;
}
#endif
/* The 64-bit high half's type must be zero. */
if ( idte.d & 0x1f00 )
goto raise_exn;
/* icebp counts as a hardware event, and bypasses the dpl check. */
if ( type != x86_swint_icebp )
@@ -1725,6 +1740,13 @@ static int inject_swint(enum x86_swint_type type,
if ( cpl > ((idte.b >> 13) & 3) )
goto raise_exn;
}
/* Is this entry present? */
if ( !(idte.b & (1u << 15)) )
{
fault_type = EXC_NP;
goto raise_exn;
}
}
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.