If the current privilege level is encoded in CS
, which is modifiable by user-mode code, why can’t user-mode code modify CS
to change CPL
?
The question is broad, but I can give some general information and links referencing the Instruction Set architecture (ISA) which describes all the instructions.
You can't MOV
or POP
a value into CS (on 286+1) so you are prevented from modifying CS that way. For example for POP
there is a rule:
The POP instruction cannot pop a value into the CS register. To load the CS register from the stack, use the RET instruction.
And the rule for MOV
is similar:
The MOV instruction cannot be used to load the CS register.
You can modify CS indirectly through syscall
, sysenter
, FAR jmp
(via call gate), FAR call
(via call gate), iret
, retf
(FAR return) or int
. You can review the ISA for each instruction and what privilege level checks are applied. You can't arbitrarily change CPL if you don't have the privilege and access rights to do so.
Under most circumstances if you have the privilege to affect a change to CPL it will be changed. If you don't have the required privileges you get an exception (privilege level checks usually involve RPL, CPL, DPL). If using conforming code segments (a different topic) you can request to execute code using a code segment with a higher privileged DPL but the CPL will remain unchanged. It is a case where the CPL and DPL (Descriptor privilege level) of CS can be different while code is executing.
1You were allowed to modify CS via POP
and MOV
on 8088/8086 processors.