[FAST486]

Fix the TSS limit validity check.
Implement I/O privilege checking.


svn path=/trunk/; revision=69424
This commit is contained in:
Aleksandar Andrejevic 2015-10-01 02:24:17 +00:00
parent 66aea017f9
commit 2efd4b6466
3 changed files with 63 additions and 2 deletions

View file

@ -628,8 +628,8 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
PFAST486_LEGACY_TSS NewLegacyTss = (PFAST486_LEGACY_TSS)&NewTss;
USHORT NewLdtr, NewEs, NewCs, NewSs, NewDs;
if (State->TaskReg.Limit < (sizeof(FAST486_TSS) - 1)
&& State->TaskReg.Limit != (sizeof(FAST486_LEGACY_TSS) - 1))
if ((State->TaskReg.Modern && State->TaskReg.Limit < (sizeof(FAST486_TSS) - 1))
|| (!State->TaskReg.Modern && State->TaskReg.Limit < (sizeof(FAST486_LEGACY_TSS) - 1)))
{
/* Invalid task register limit */
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, State->TaskReg.Selector);
@ -882,6 +882,7 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
State->TaskReg.Selector = Selector;
State->TaskReg.Base = NewTssAddress;
State->TaskReg.Limit = NewTssLimit;
State->TaskReg.Modern = (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE);
if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
{

View file

@ -1599,6 +1599,54 @@ Fast486WriteModrmDwordOperands(PFAST486_STATE State,
return TRUE;
}
FORCEINLINE
BOOLEAN
FASTCALL
Fast486IoPrivilegeCheck(PFAST486_STATE State, USHORT Port)
{
UCHAR Bits;
ULONG Location;
FAST486_TSS Tss;
/* Access is always allowed if the CPL is less than or equal to the IOPL */
if (State->Cpl <= State->Flags.Iopl) return TRUE;
/* Legacy Task State Segments have no IOPB */
if (!State->TaskReg.Modern) return FALSE;
/* Read the TSS */
if (!Fast486ReadLinearMemory(State, State->TaskReg.Base, &Tss, sizeof(FAST486_TSS), FALSE))
{
/* Exception occurred */
return FALSE;
}
Location = State->TaskReg.Base + HIWORD(Tss.IopbOffset) + (Port >> 3);
if (Location > State->TaskReg.Limit)
{
/* Access denied */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
/* Read the appropriate bit from the TSS IOPB */
if (!Fast486ReadLinearMemory(State, Location, &Bits, sizeof(UCHAR), FALSE))
{
/* Exception occurred */
return FALSE;
}
if (Bits & (1 << (Port & 0x07)))
{
/* Access denied */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
return TRUE;
}
#ifndef FAST486_NO_FPU
FORCEINLINE

View file

@ -790,6 +790,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeInByte)
Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
}
if (!Fast486IoPrivilegeCheck(State, Port)) return;
/* Read a byte from the I/O port */
State->IoReadCallback(State, Port, &Data, 1, sizeof(UCHAR));
@ -828,6 +830,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIn)
Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
}
if (!Fast486IoPrivilegeCheck(State, Port)) return;
if (Size)
{
ULONG Data;
@ -876,6 +880,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte)
Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
}
if (!Fast486IoPrivilegeCheck(State, Port)) return;
/* Read the value from AL */
Data = State->GeneralRegs[FAST486_REG_EAX].LowByte;
@ -914,6 +920,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOut)
Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
}
if (!Fast486IoPrivilegeCheck(State, Port)) return;
if (Size)
{
/* Get the value from EAX */
@ -5836,6 +5844,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
TOGGLE_OPSIZE(OperandSize);
TOGGLE_ADSIZE(AddressSize);
if (!Fast486IoPrivilegeCheck(State, State->GeneralRegs[FAST486_REG_EDX].LowWord)) return;
/* Calculate the size */
if (Opcode == 0x6C) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
@ -5974,6 +5984,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOuts)
TOGGLE_OPSIZE(OperandSize);
TOGGLE_ADSIZE(AddressSize);
if (!Fast486IoPrivilegeCheck(State, State->GeneralRegs[FAST486_REG_EDX].LowWord)) return;
/* Calculate the size */
if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);