mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[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. svn path=/trunk/; revision=65280
This commit is contained in:
parent
453e370737
commit
e42640b500
5 changed files with 109 additions and 20 deletions
|
@ -553,7 +553,12 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
|
|||
|
||||
/* 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 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
|
|||
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
|
||||
{
|
||||
|
|
|
@ -594,16 +594,12 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
|
|||
{
|
||||
/* 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 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
|
|||
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 @@ Fast486ProcessGate(PFAST486_STATE State, USHORT Selector, ULONG Offset, BOOLEAN
|
|||
|
||||
default:
|
||||
{
|
||||
/* Security check for jumps and calls only */
|
||||
if (State->Cpl != Descriptor.Dpl)
|
||||
{
|
||||
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -475,7 +475,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl)
|
|||
|
||||
/* 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;
|
||||
|
|
|
@ -4474,6 +4474,63 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar)
|
|||
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 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
|
|||
/* 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 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
|
|||
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 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
|
|||
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 (OldCpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
|
||||
if (OldCpl == 0) State->Flags.Iopl = NewFlags.Iopl;
|
||||
|
||||
if (GET_SEGMENT_RPL(CodeSel) > Cpl)
|
||||
if (State->Cpl > OldCpl)
|
||||
{
|
||||
/* Update the CPL */
|
||||
Cpl = Fast486GetCurrentPrivLevel(State);
|
||||
|
||||
/* 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))
|
||||
{
|
||||
|
|
|
@ -1804,7 +1804,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
|
|||
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 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue