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