Made INSTR_EmulateInstruction return the exception code.

Don't allow intXX instructions from 32-bit code (based on a patch by
Jukka Heinonen).
This commit is contained in:
Alexandre Julliard 2003-05-14 19:41:16 +00:00
parent 28b64db6d5
commit 0b34697abb
3 changed files with 62 additions and 50 deletions

View File

@ -776,8 +776,7 @@ static void do_segv( CONTEXT *context, int trap_code, void *cr2, int err_code )
case T_SEGNPFLT: /* Segment not present exception */ case T_SEGNPFLT: /* Segment not present exception */
case T_PROTFLT: /* General protection fault */ case T_PROTFLT: /* General protection fault */
case T_UNKNOWN: /* Unknown fault code */ case T_UNKNOWN: /* Unknown fault code */
if (INSTR_EmulateInstruction( context )) return; if (!(rec.ExceptionCode = INSTR_EmulateInstruction( context ))) return;
rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
break; break;
case T_PAGEFLT: /* Page fault */ case T_PAGEFLT: /* Page fault */
#ifdef FAULT_ADDRESS #ifdef FAULT_ADDRESS

View File

@ -105,7 +105,7 @@ extern LPVOID DOSMEM_MapDosToLinear(UINT); /* linear DOS to Wine */
extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
/* memory/instr.c */ /* memory/instr.c */
extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context ); extern DWORD INSTR_EmulateInstruction( CONTEXT86 *context );
/* msdos/ioports.c */ /* msdos/ioports.c */
extern DWORD IO_inport( int port, int count ); extern DWORD IO_inport( int port, int count );

View File

@ -396,17 +396,18 @@ static void INSTR_outport( WORD port, int size, DWORD val, CONTEXT86 *context )
/*********************************************************************** /***********************************************************************
* INSTR_EmulateInstruction * INSTR_EmulateInstruction
* *
* Emulate a privileged instruction. Returns TRUE if emulation successful. * Emulate a privileged instruction.
* Returns exception code, or 0 if emulation successful.
*/ */
BOOL INSTR_EmulateInstruction( CONTEXT86 *context ) DWORD INSTR_EmulateInstruction( CONTEXT86 *context )
{ {
int prefix, segprefix, prefixlen, len, repX, long_op, long_addr; int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
SEGPTR gpHandler;
BYTE *instr; BYTE *instr;
DWORD ret = EXCEPTION_PRIV_INSTRUCTION;
long_op = long_addr = (!ISV86(context) && IS_SELECTOR_32BIT(context->SegCs)); long_op = long_addr = (!ISV86(context) && IS_SELECTOR_32BIT(context->SegCs));
instr = make_ptr( context, context->SegCs, context->Eip, TRUE ); instr = make_ptr( context, context->SegCs, context->Eip, TRUE );
if (!instr) return FALSE; if (!instr) return ret;
/* First handle any possible prefix */ /* First handle any possible prefix */
@ -480,7 +481,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
} }
add_stack(context, long_op ? 4 : 2); add_stack(context, long_op ? 4 : 2);
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
} }
} }
break; /* Unable to emulate it */ break; /* Unable to emulate it */
@ -494,7 +495,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
ERR("mov eax,cr0 at 0x%08lx, EAX=0x%08lx\n", ERR("mov eax,cr0 at 0x%08lx, EAX=0x%08lx\n",
context->Eip,context->Eax ); context->Eip,context->Eax );
context->Eip += prefixlen+3; context->Eip += prefixlen+3;
return TRUE; return 0;
default: default:
break; /*fallthrough to bad instruction handling */ break; /*fallthrough to bad instruction handling */
} }
@ -516,12 +517,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
ERR("mov cr4,eax at 0x%08lx\n",context->Eip); ERR("mov cr4,eax at 0x%08lx\n",context->Eip);
context->Eax = 0; context->Eax = 0;
context->Eip += prefixlen+3; context->Eip += prefixlen+3;
return TRUE; return 0;
case 0xc0: /* mov cr0, eax */ case 0xc0: /* mov cr0, eax */
ERR("mov cr0,eax at 0x%08lx\n",context->Eip); ERR("mov cr0,eax at 0x%08lx\n",context->Eip);
context->Eax = 0x10; /* FIXME: set more bits ? */ context->Eax = 0x10; /* FIXME: set more bits ? */
context->Eip += prefixlen+3; context->Eip += prefixlen+3;
return TRUE; return 0;
default: /* fallthrough to illegal instruction */ default: /* fallthrough to illegal instruction */
break; break;
} }
@ -535,7 +536,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
context->SegFs = seg; context->SegFs = seg;
add_stack(context, long_op ? 4 : 2); add_stack(context, long_op ? 4 : 2);
context->Eip += prefixlen + 2; context->Eip += prefixlen + 2;
return TRUE; return 0;
} }
} }
break; break;
@ -547,7 +548,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
context->SegGs = seg; context->SegGs = seg;
add_stack(context, long_op ? 4 : 2); add_stack(context, long_op ? 4 : 2);
context->Eip += prefixlen + 2; context->Eip += prefixlen + 2;
return TRUE; return 0;
} }
} }
break; break;
@ -558,7 +559,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
long_addr, segprefix, &len )) long_addr, segprefix, &len ))
{ {
context->Eip += prefixlen + len; context->Eip += prefixlen + len;
return TRUE; return 0;
} }
break; break;
} }
@ -631,7 +632,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
} }
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
} }
return TRUE; return 0;
case 0x8e: /* mov XX,segment_reg */ case 0x8e: /* mov XX,segment_reg */
{ {
@ -649,25 +650,25 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
case 0: case 0:
context->SegEs = seg; context->SegEs = seg;
context->Eip += prefixlen + len + 1; context->Eip += prefixlen + len + 1;
return TRUE; return 0;
case 1: /* cs */ case 1: /* cs */
break; break;
case 2: case 2:
context->SegSs = seg; context->SegSs = seg;
context->Eip += prefixlen + len + 1; context->Eip += prefixlen + len + 1;
return TRUE; return 0;
case 3: case 3:
context->SegDs = seg; context->SegDs = seg;
context->Eip += prefixlen + len + 1; context->Eip += prefixlen + len + 1;
return TRUE; return 0;
case 4: case 4:
context->SegFs = seg; context->SegFs = seg;
context->Eip += prefixlen + len + 1; context->Eip += prefixlen + len + 1;
return TRUE; return 0;
case 5: case 5:
context->SegGs = seg; context->SegGs = seg;
context->Eip += prefixlen + len + 1; context->Eip += prefixlen + len + 1;
return TRUE; return 0;
case 6: /* unused */ case 6: /* unused */
case 7: /* unused */ case 7: /* unused */
break; break;
@ -681,19 +682,28 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
long_addr, segprefix, &len )) long_addr, segprefix, &len ))
{ {
context->Eip += prefixlen + len; context->Eip += prefixlen + len;
return TRUE; return 0;
} }
break; /* Unable to emulate it */ break; /* Unable to emulate it */
case 0xcd: /* int <XX> */ case 0xcd: /* int <XX> */
if(!Dosvm.EmulateInterruptPM && !DPMI_LoadDosSystem()) if (IS_SELECTOR_SYSTEM(context->SegCs))
ERR("could not initialize interrupt handling\n"); {
else { /* Win32 applications cannot use interrupts */
context->Eip += prefixlen + 2; ret = EXCEPTION_ACCESS_VIOLATION;
Dosvm.EmulateInterruptPM( context, instr[1] ); break;
return TRUE; }
} else if (!Dosvm.EmulateInterruptPM && !DPMI_LoadDosSystem())
break; /* Unable to emulate it */ {
ERR("could not initialize interrupt handling\n");
}
else
{
context->Eip += prefixlen + 2;
Dosvm.EmulateInterruptPM( context, instr[1] );
return 0;
}
break; /* Unable to emulate it */
case 0xcf: /* iret */ case 0xcf: /* iret */
if (long_op) if (long_op)
@ -712,12 +722,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
SET_LOWORD(context->EFlags,*stack); SET_LOWORD(context->EFlags,*stack);
add_stack(context, 3*sizeof(WORD)); /* Pop the return address and flags */ add_stack(context, 3*sizeof(WORD)); /* Pop the return address and flags */
} }
return TRUE; return 0;
case 0xe4: /* inb al,XX */ case 0xe4: /* inb al,XX */
SET_LOBYTE(context->Eax,INSTR_inport( instr[1], 1, context )); SET_LOBYTE(context->Eax,INSTR_inport( instr[1], 1, context ));
context->Eip += prefixlen + 2; context->Eip += prefixlen + 2;
return TRUE; return 0;
case 0xe5: /* in (e)ax,XX */ case 0xe5: /* in (e)ax,XX */
if (long_op) if (long_op)
@ -725,12 +735,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
else else
SET_LOWORD(context->Eax, INSTR_inport( instr[1], 2, context )); SET_LOWORD(context->Eax, INSTR_inport( instr[1], 2, context ));
context->Eip += prefixlen + 2; context->Eip += prefixlen + 2;
return TRUE; return 0;
case 0xe6: /* outb XX,al */ case 0xe6: /* outb XX,al */
INSTR_outport( instr[1], 1, LOBYTE(context->Eax), context ); INSTR_outport( instr[1], 1, LOBYTE(context->Eax), context );
context->Eip += prefixlen + 2; context->Eip += prefixlen + 2;
return TRUE; return 0;
case 0xe7: /* out XX,(e)ax */ case 0xe7: /* out XX,(e)ax */
if (long_op) if (long_op)
@ -738,12 +748,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
else else
INSTR_outport( instr[1], 2, LOWORD(context->Eax), context ); INSTR_outport( instr[1], 2, LOWORD(context->Eax), context );
context->Eip += prefixlen + 2; context->Eip += prefixlen + 2;
return TRUE; return 0;
case 0xec: /* inb al,dx */ case 0xec: /* inb al,dx */
SET_LOBYTE(context->Eax, INSTR_inport( LOWORD(context->Edx), 1, context ) ); SET_LOBYTE(context->Eax, INSTR_inport( LOWORD(context->Edx), 1, context ) );
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
case 0xed: /* in (e)ax,dx */ case 0xed: /* in (e)ax,dx */
if (long_op) if (long_op)
@ -751,12 +761,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
else else
SET_LOWORD(context->Eax, INSTR_inport( LOWORD(context->Edx), 2, context )); SET_LOWORD(context->Eax, INSTR_inport( LOWORD(context->Edx), 2, context ));
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
case 0xee: /* outb dx,al */ case 0xee: /* outb dx,al */
INSTR_outport( LOWORD(context->Edx), 1, LOBYTE(context->Eax), context ); INSTR_outport( LOWORD(context->Edx), 1, LOBYTE(context->Eax), context );
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
case 0xef: /* out dx,(e)ax */ case 0xef: /* out dx,(e)ax */
if (long_op) if (long_op)
@ -764,32 +774,35 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
else else
INSTR_outport( LOWORD(context->Edx), 2, LOWORD(context->Eax), context ); INSTR_outport( LOWORD(context->Edx), 2, LOWORD(context->Eax), context );
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
case 0xfa: /* cli, ignored */ case 0xfa: /* cli, ignored */
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
case 0xfb: /* sti, ignored */ case 0xfb: /* sti, ignored */
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return TRUE; return 0;
} }
/* Check for Win16 __GP handler */ /* Check for Win16 __GP handler */
gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) ); if (!IS_SELECTOR_SYSTEM(context->SegCs))
if (gpHandler)
{ {
WORD *stack = get_stack( context ); SEGPTR gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) );
*--stack = context->SegCs; if (gpHandler)
*--stack = context->Eip; {
add_stack(context, -2*sizeof(WORD)); WORD *stack = get_stack( context );
*--stack = context->SegCs;
*--stack = context->Eip;
add_stack(context, -2*sizeof(WORD));
context->SegCs = SELECTOROF( gpHandler ); context->SegCs = SELECTOROF( gpHandler );
context->Eip = OFFSETOF( gpHandler ); context->Eip = OFFSETOF( gpHandler );
return TRUE; return 0;
}
} }
return FALSE; /* Unable to emulate it */ return ret; /* Unable to emulate it */
} }
#endif /* __i386__ */ #endif /* __i386__ */