[FAST486]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Thu, 1 Oct 2015 02:24:17 +0000 (02:24 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Thu, 1 Oct 2015 02:24:17 +0000 (02:24 +0000)
Fix the TSS limit validity check.
Implement I/O privilege checking.

svn path=/trunk/; revision=69424

reactos/lib/fast486/common.c
reactos/lib/fast486/common.inl
reactos/lib/fast486/opcodes.c

index bc31292..a34c8ef 100644 (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;
 
     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);
     {
         /* 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.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)
     {
 
     if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
     {
index f029187..f74e8ee 100644 (file)
@@ -1599,6 +1599,54 @@ Fast486WriteModrmDwordOperands(PFAST486_STATE State,
     return TRUE;
 }
 
     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
 #ifndef FAST486_NO_FPU
 
 FORCEINLINE
index bc0aa50..e8e9028 100644 (file)
@@ -790,6 +790,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeInByte)
         Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
     }
 
         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));
 
     /* 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;
     }
 
         Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
     }
 
+    if (!Fast486IoPrivilegeCheck(State, Port)) return;
+
     if (Size)
     {
         ULONG Data;
     if (Size)
     {
         ULONG Data;
@@ -876,6 +880,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte)
         Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
     }
 
         Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
     }
 
+    if (!Fast486IoPrivilegeCheck(State, Port)) return;
+
     /* Read the value from AL */
     Data = State->GeneralRegs[FAST486_REG_EAX].LowByte;
 
     /* 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;
     }
 
         Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
     }
 
+    if (!Fast486IoPrivilegeCheck(State, Port)) return;
+
     if (Size)
     {
         /* Get the value from EAX */
     if (Size)
     {
         /* Get the value from EAX */
@@ -5836,6 +5844,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
     TOGGLE_OPSIZE(OperandSize);
     TOGGLE_ADSIZE(AddressSize);
 
     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);
     /* 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);
 
     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);
     /* Calculate the size */
     if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
     else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);