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=6…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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=…
==============================================================================
--- 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…
==============================================================================
--- 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;
}