Privileged transfer is more complex, but it can be summed up into two main classes.
1. For code snippets, you can only access from low to high.
2. For data segments, only high to low access.
And then decompose:
Code snippets are from low to high (consistent, target privilege level to visitor privilege level) or the same (non-uniform).
Data segments are always non-consistent.
The descriptor itself is a data segment. For example, the call door, TTS itself is a data segment, so must be from the high privilege level
Access to low privileged level, that is, visitor privilege level <= door, TTS for DPL. (the value is less than or equal to the privilege level).
Access to the code snippet through the door, whether consistent or non-uniform, is in principle accessed from low to high.
On a non-uniform piece of code, only the JMP directive requires that the visitor privilege level be equal to the target code segment accessed through the door,
Everything else can be accessed from low to high.
So the condition to be called through the door is: 1. First you have access to the door itself (from high to low), and then you can start from low to high.
Finally add RPL. When the RPL is lower than the CPL, the RPL covers the CPL. This way even if the segment of the visitor has sufficient privilege level but RPL
Not enough to access high-privileged data. Prevent low privilege levels from constructing high privilege level selectors to access high privilege
Level of data (the current RPL will be placed in the RPL of the selector).
If the target code snippet has a low privilege level, it cannot be transferred through call and JMP. You can only jump through the RETF command.
Why is it possible to reduce privilege levels through RETF?
Since call,jmp is accessed from the caller's low privileged level to the callee's high privileged level (the non-Uniform code snippet is equal),
Then, when RET/RETF is returned from the callee's high privileged level to the caller's low privilege level, the processor's judgment
The logic is that the RPL,DPL to return the target code (the caller) should be lower than the current code snippet (callee). When the caller
The RPL of the code snippet is lower than the current CPL, it should be switched to a lower RPL privilege level run.
Of course, the original caller's CS,EIP is the processor before the call to save the stack, but if the current code snippet in the
High-level, you can access to jump to the low-privileged selection of sub-and descriptor, stack segment, then we can put
The low-privileged SS,ESP,CS,EIP to enter is constructed manually by the CPU before it calls the high privilege level.
The RETF is then called to simulate the return of the caller in a low-privileged environment from a high-privileged called environment, thereby implementing the
High privilege level jumps to low privilege levels.
Here the jump must be used RETF, because RET although can achieve long jump, but it does not return CS, and switch privilege level
is determined by the RPL of CS.
Ret:
(IP) = ((ss) *16+ (SP))
(sp) = (sp) +2
->pop IP
RETF:
(IP) = ((ss) *16+ (SP))
(sp) = (sp) +2
(cs) = ((ss) *16+ (SP))
(sp) = (sp) +2
->pop IP
->pop CS
Code snippets of different privileged levels use different stack segments, in order to prevent low privilege code snippets from heavily using highly privileged
stack to cause the kernel to crash, so switch between different privilege levels to stack transfer, TTS is for low to high access
Indicates the SS and ESP of the target code snippet, while the original SS and ESP are pressed into the new stack for return invocation.
Direct jump (Jmp,call) to the consistent code segment only from low to high, and CPL can not be changed, the non-uniform code snippet can only be
Between the same privileged levels.
A free jump can also be achieved using the call gate in both consistent and non-uniform code segments.