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
?

- 46,082
- 8
- 107
- 198

- 3,256
- 2
- 24
- 40
-
It can: just execute `syscall` or `int3` ;) – Ruslan Sep 02 '19 at 16:23
-
@Ruslan SYSCALL invokes an OS system-call handler at privilege level 0, but in that case, the OS is the one who put the address in CS (CS point to the address of the handler ), not the user – zerocool Sep 02 '19 at 16:32
-
Not, it's not the OS directly: it's the `syscall` instruction which changes `cs`, along with a bunch of other registers. Same for interrupt handlers (though they don't use MSRs to find targets, instead using interrupt gates in the IDT). – Ruslan Sep 02 '19 at 16:35
-
But who configure those address in the first place it's the OS roll to set up the IDT for example at boot time – zerocool Sep 02 '19 at 16:37
-
If your userspace program has direct access to the GDT, IDT or LDT, it's a security problem in your OS. Of course the OS has to create all the descriptors. And it's not going to let userspace to switch CPL arbitrarily. – Ruslan Sep 02 '19 at 16:39
-
What is your actual question? Is it "What mechanism prevents change of CPL on loading of a selector into CS?"? Or maybe "What is the rationale for this impossibility?"? – Ruslan Sep 02 '19 at 16:41
-
What mechanism prevents change of CPL on loading of a selector into CS in user-mode? – zerocool Sep 02 '19 at 16:42
-
What environment are you testing on? QEMU? Bochs? Real hardware (There is a reason I ask that question first). Second question. How are you changing _CS_? (What instructions). `MOV` and `POP` can't alter _CS_ or they throw an exception. That leaves FAR `CALL` and `JMP`'s indirectly through Call Gates (or indirectly via syscall/traps/interrupts etc) or using `IRED` or `RETF` (Far return). The instruction set reference for the instruction you use to modify _CS_ will include the rules what CPL changes are allowed (privilege level changes involve checks with RPL and the the DPL of the _CS_) – Michael Petch Sep 02 '19 at 16:52
-
This question is based on a [faulty assumption](https://www.reddit.com/r/asm/comments/6c3rnv/why_exactly_mov_csxx_is_an_restricted_instruction/). – Hans Passant Sep 02 '19 at 16:58
-
@MichaelPetch let's say everything that can change it ( FAR CALL/JMP IRET/IRETD/IRETQ ) – zerocool Sep 02 '19 at 17:03
-
I should've also asked a question about the title of this Q. _modifying CS from UserMode doesn't affect CPL_. Was there some specific piece of code that you used to modify CS that resulted in no change? Usually with changing CS indirectly (via other instructions previously listed) one of two things will happen. You'll get an exception because you don't have proper permission to change the CPL to another or you are transitioned into another ring and a CPL change will take place (there are some exceptions if you use conforming code segments where CPL doesn't change and code runs with CPL<>DPL). – Michael Petch Sep 02 '19 at 17:08
-
@MichaelPetch there is no piece of code actually, just a guy asked me and I couldn't answer him – zerocool Sep 02 '19 at 17:11
-
1The real answer as to what happens with each instruction that may alter CPL (JMP/CALL/IRET/RETF etc) is in the Instruction Set Architecture reference for each instruction. https://www.felixcloutier.com/x86/ – Michael Petch Sep 02 '19 at 17:11
-
I will check it – zerocool Sep 02 '19 at 17:13
-
1I have a hunch that whoever asked you the question is/was confused although I can't say since I can't ask them these questions directly. – Michael Petch Sep 02 '19 at 17:14
-
@MichaelPetch Normally I don't give this type of questions a big deal but when a student stops you at class and I promise him a good answer, so I better do it (^_^) – zerocool Sep 02 '19 at 17:17
-
@MichaelPetch question is taken verbatim from from the book practical reverse engineering, so there ya go. – Assaf Levy Aug 17 '20 at 12:32
1 Answers
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.
Footnotes
1You were allowed to modify CS via POP
and MOV
on 8088/8086 processors.

- 46,082
- 8
- 107
- 198