Jump to userland
Description
Once you’ve loaded the binary into memory, with separate segment for code and data, you should be able to execute the rom code. This code should run in ring3, so it means that it should be unprivileged.
Recommended methodology
The processor state needed in order to launch an unprivileged program is the following:
Register | State |
---|---|
ds | DS_USER | RING3_DPL |
es | DS_USER | RING3_DPL |
ss | SS_USER | RING3_DPL |
esp | SS_USER upper address |
eflags | Enable interrupts |
cs | CS_USER | RING3_DPL |
eip | Linear rom entry point |
According to the intel manual:
Privilege level checking also occurs when the SS register is loaded with the
segment selector for a stack segment. Here all privilege levels related to the
stack segment must match the CPL; that is, the CPL, the RPL of the stack-
segment selector, and the DPL of the stack-segment descriptor must be the same.
If the RPL and DPL are not equal to the CPL, a general-protection exception
(#GP) is generated.
It implies that we must change the cs
and ss
privilege at the same time.
Therefore, we shall use the iret
instruction to jump to userland.
With a hand-crafted stack, iret
sets every register aforementioned except ds
and es
so we must set them beforehand.
Possible bug causes
- Memory mapping
- Event manager
- VGA driver
- Filesystem
- Syscall wrapper
So be sure to test every part of your kernel before jumping to userland.