Vol. 3 5-29
PROTECTION
intended to execute returns from procedures that were called with a CALL instruc-
tion. It does not support returns from a JMP instruction, because the JMP instruction
does not save a return instruction pointer on the stack.
A near return only transfers program control within the current code segment; there-
fore, the processor performs only a limit check. When the processor pops the return
instruction pointer from the stack into the EIP register, it checks that the pointer does
not exceed the limit of the current code segment.
On a far return at the same privilege level, the processor pops both a segment
selector for the code segment being returned to and a return instruction pointer from
the stack. Under normal conditions, these pointers should be valid, because they
were pushed on the stack by the CALL instruction. However, the processor performs
privilege checks to detect situations where the current procedure might have altered
the pointer or failed to maintain the stack properly.
A far return that requires a privilege-level change is only allowed when returning to a
less privileged level (that is, the DPL of the return code segment is numerically
greater than the CPL). The processor uses the RPL field from the CS register value
saved for the calling procedure (see
Figure 5-13) to determine if a return to a numer-
ically higher privilege level is required. If the RPL is numerically greater (less privi-
leged) than the CPL, a return across privilege levels occurs.
The processor performs the following steps when performing a far return to a calling
procedure (see Figures 6-2 and 6-4 in the Intel® 64 and IA-32 Architectures Soft-
ware Developer’s Manual, Volume 1, for an illustration of the stack contents prior to
and after a return):
1. Checks the RPL field of the saved CS register value to determine if a privilege
level change is required on the return.
2. Loads the CS and EIP registers with the values on the called procedure’s stack.
(Type and privilege level checks are performed on the code-segment descriptor
and RPL of the code- segment selector.)
3. (If the RET instruction includes a parameter count operand and the return
requires a privilege level change.) Adds the parameter count (in bytes obtained
from the RET instruction) to the current ESP register value (after popping the CS
and EIP values), to step past the parameters on the called procedure’s stack. The
resulting value in the ESP register points to the saved SS and ESP values for the
calling procedure’s stack. (Note that the byte count in the RET instruction must
be chosen to match the parameter count in the call gate that the calling
procedure referenced when it made the original call multiplied by the size of the
parameters.)
4. (If the return requires a privilege level change.) Loads the SS and ESP registers
with the saved SS and ESP values and switches back to the calling procedure’s
stack. The SS and ESP values for the called procedure’s stack are discarded. Any
limit violations detected while loading the stack-segment selector or stack
pointer cause a general-protection exception (#GP) to be generated. The new
stack-segment descriptor is also checked for type and privilege violations.