Author: aandrejevic
Date: Thu Nov  6 05:16:14 2014
New Revision: 65280

URL: http://svn.reactos.org/svn/reactos?rev=65280&view=rev
Log:
[FAST486]
Fix the limit calculation when using page granularity.
RETF can also perform inter-privilege returns.
Fix the privilege checks when loading CS. DPL != CPL is only a #GP
when we're doing a jump or a call.


Modified:
    trunk/reactos/lib/fast486/common.c
    trunk/reactos/lib/fast486/common.inl
    trunk/reactos/lib/fast486/extraops.c
    trunk/reactos/lib/fast486/opcodes.c
    trunk/reactos/lib/fast486/opgroups.c

Modified: trunk/reactos/lib/fast486/common.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.c?rev=65280&r1=65279&r2=65280&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/common.c  [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.c  [iso-8859-1] Thu Nov  6 05:16:14 2014
@@ -553,7 +553,12 @@
 
     /* Calculate the limit of the new TSS */
     NewTssLimit = NewTssDescriptor.Limit | (NewTssDescriptor.LimitHigh << 16);
-    if (NewTssDescriptor.Granularity) NewTssLimit <<= 12;
+
+    if (NewTssDescriptor.Granularity)
+    {
+        NewTssLimit <<= 12;
+        NewTssLimit |= 0x00000FFF;
+    }
 
     if (NewTssLimit < sizeof(FAST486_TSS))
     {
@@ -739,7 +744,12 @@
         State->Ldtr.Selector = NewTss.Ldtr;
         State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | 
(GdtEntry.BaseHigh << 24);
         State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-        if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+        if (GdtEntry.Granularity)
+        {
+            State->Ldtr.Limit <<= 12;
+            State->Ldtr.Limit |= 0x00000FFF;
+        }
     }
     else
     {

Modified: trunk/reactos/lib/fast486/common.inl
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.inl?rev=65280&r1=65279&r2=65280&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/common.inl        [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.inl        [iso-8859-1] Thu Nov  6 
05:16:14 2014
@@ -594,16 +594,12 @@
             {
                 /* Regular code segment */
 
-                if ((GET_SEGMENT_RPL(Selector) > 
Fast486GetCurrentPrivLevel(State))
-                    || (Fast486GetCurrentPrivLevel(State) != GdtEntry.Dpl))
+                if ((GET_SEGMENT_RPL(Selector) < 
Fast486GetCurrentPrivLevel(State)))
                 {
                     Fast486ExceptionWithErrorCode(State, Exception, Selector);
                     return FALSE;
                 }
             }
-
-            /* Update CPL */
-            State->Cpl = GET_SEGMENT_RPL(Selector);
         }
         else
         {
@@ -653,7 +649,11 @@
         CachedDescriptor->Size = GdtEntry.Size;
 
         /* Check for page granularity */
-        if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12;
+        if (GdtEntry.Granularity)
+        {
+            CachedDescriptor->Limit <<= 12;
+            CachedDescriptor->Limit |= 0x00000FFF;
+        }
     }
     else
     {
@@ -730,6 +730,13 @@
 
         default:
         {
+            /* Security check for jumps and calls only */
+            if (State->Cpl != Descriptor.Dpl)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 
Selector);
+                return FALSE;
+            }
+
             return TRUE;
         }
     }

Modified: trunk/reactos/lib/fast486/extraops.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/extraops.c?rev=65280&r1=65279&r2=65280&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/extraops.c        [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/extraops.c        [iso-8859-1] Thu Nov  6 
05:16:14 2014
@@ -475,7 +475,12 @@
 
     /* Calculate the limit */
     Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-    if (GdtEntry.Granularity) Limit <<= 12;
+
+    if (GdtEntry.Granularity)
+    {
+        Limit <<= 12;
+        Limit |= 0x00000FFF;
+    }
 
     /* Set ZF */
     State->Flags.Zf = TRUE;

Modified: trunk/reactos/lib/fast486/opcodes.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opcodes.c?rev=65280&r1=65279&r2=65280&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] Thu Nov  6 05:16:14 2014
@@ -4474,6 +4474,63 @@
         return;
     }
 
+    if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && 
!State->Flags.Vm)
+    {
+        INT i;
+        INT OldCpl = Fast486GetCurrentPrivLevel(State);
+        ULONG StackPtr;
+        ULONG StackSel;
+        
+        if (GET_SEGMENT_RPL(Segment) > OldCpl)
+        {
+            /* Pop ESP */
+            if (!Fast486StackPop(State, &StackPtr))
+            {
+                /* Exception */
+                return;
+            }
+
+            /* Pop SS */
+            if (!Fast486StackPop(State, &StackSel))
+            {
+                /* Exception */
+                return;
+            }
+
+            /* Load new SS */
+            if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
+            {
+                /* Exception */
+                return;
+            }
+
+            /* Set ESP */
+            if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
+            else State->GeneralRegs[FAST486_REG_ESP].LowWord = 
LOWORD(StackPtr);
+        }
+
+        /* Update the CPL */
+        State->Cpl = GET_SEGMENT_RPL(Segment);
+
+        if (State->Cpl > OldCpl)
+        {
+            /* Check segment security */
+            for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
+            {
+                /* Don't check CS or SS */
+                if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
+
+                if ((State->Cpl > State->SegmentRegs[i].Dpl)
+                    && (!State->SegmentRegs[i].Executable
+                    || !State->SegmentRegs[i].DirConf))
+                {
+                    /* Load the NULL descriptor in the segment */
+                    if (!Fast486LoadSegment(State, i, 0)) return;
+                }
+            }
+        }
+    }
+
     /* Load new (E)IP, and if necessary, pop the parameters */
     if (Size)
     {
@@ -4582,7 +4639,7 @@
     /* Check for protected mode */
     if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
     {
-        INT Cpl = Fast486GetCurrentPrivLevel(State);
+        INT OldCpl = Fast486GetCurrentPrivLevel(State);
 
         if (State->Flags.Vm)
         {
@@ -4660,7 +4717,7 @@
         if (Size) State->InstPtr.Long = InstPtr;
         else State->InstPtr.LowWord = LOWORD(InstPtr);
 
-        if (GET_SEGMENT_RPL(CodeSel) > Cpl)
+        if (GET_SEGMENT_RPL(CodeSel) > OldCpl)
         {
             /* Pop ESP */
             if (!Fast486StackPop(State, &StackPtr))
@@ -4688,27 +4745,27 @@
             else State->GeneralRegs[FAST486_REG_ESP].LowWord = 
LOWORD(StackPtr);
         }
 
+        /* Update the CPL */
+        State->Cpl = GET_SEGMENT_RPL(CodeSel);
+
         /* Set the new flags */
         if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK;
         else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK;
         State->Flags.AlwaysSet = TRUE;
 
         /* Set additional flags */
-        if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
-        if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
-
-        if (GET_SEGMENT_RPL(CodeSel) > Cpl)
-        {
-            /* Update the CPL */
-            Cpl = Fast486GetCurrentPrivLevel(State);
-
+        if (OldCpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
+        if (OldCpl == 0) State->Flags.Iopl = NewFlags.Iopl;
+
+        if (State->Cpl > OldCpl)
+        {
             /* Check segment security */
             for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
             {
                 /* Don't check CS or SS */
                 if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
 
-                if ((Cpl > State->SegmentRegs[i].Dpl)
+                if ((State->Cpl > State->SegmentRegs[i].Dpl)
                     && (!State->SegmentRegs[i].Executable
                     || !State->SegmentRegs[i].DirConf))
                 {

Modified: trunk/reactos/lib/fast486/opgroups.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opgroups.c?rev=65280&r1=65279&r2=65280&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/opgroups.c        [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opgroups.c        [iso-8859-1] Thu Nov  6 
05:16:14 2014
@@ -1804,7 +1804,12 @@
             State->Ldtr.Selector = Selector;
             State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | 
(GdtEntry.BaseHigh << 24);
             State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-            if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+            if (GdtEntry.Granularity)
+            {
+                State->Ldtr.Limit <<= 12;
+                State->Ldtr.Limit |= 0x00000FFF;
+            }
 
             break;
         }
@@ -1886,7 +1891,12 @@
             State->TaskReg.Selector = Selector;
             State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | 
(GdtEntry.BaseHigh << 24);
             State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-            if (GdtEntry.Granularity) State->TaskReg.Limit <<= 12;
+
+            if (GdtEntry.Granularity)
+            {
+                State->TaskReg.Limit <<= 12;
+                State->TaskReg.Limit |= 0x00000FFF;
+            }
 
             break;
         }


Reply via email to