4

I'm working on some low level os code (64-bit) and I'm trying to figure out how to switch from CPL0 to CPL3. The problem is this little sentence in the Intel developer manual I ran across: ''...the processor does not allow a transfer of program control from a procedure running at a CPL of 0,1, or 2 to a procedure running at a CPL or 3, except on return. "

The TSS (Task State Segment) doesn't even have a stack pointer so what will CPL3 code use for a stack? I know this is possible (else how else would the OS launch any application code) but I can't find any documentation on it. It seems like you'll have to push the address of some CPL3 code on to the stack to trick the processor into running CPL3 code, but that sounds kind of hacy. Do you guys know of a better way to do this? Any help is much appreciated.

durron597
  • 31,968
  • 17
  • 99
  • 158
ballaw
  • 1,489
  • 6
  • 20
  • 28
  • When you say the TSS doesn't even have a stack pointer, do you mean that your CPL3 code is just starting up for the first time? EDIT: What you're looking for is probably on the kernel stack: http://stackoverflow.com/questions/4709582/when-starting-a-system-call-how-are-user-mode-ss-and-esp-saved-e-g-in-linux – Aaron Altman Sep 16 '12 at 14:13

1 Answers1

4

In x86, if you want to pass control back from more privileged level to less priviliged, you must use iret instruction. Create manually top of the stack in accordance to the structure expected by iret instruction (ss, esp, eflags, cs && eip) and invoke iret.

Note, example is for x86. The x64 go in the same way but use another reguisters and possibly slightly different stack layout expected.

VOID FASTCALL JumpFromCr0ToCr3(CONST ULONG cr3_eip, CONST USHORT cr3_cs , CONST ULONG cr3_flags, CONST ULONG cr3_esp, CONST USHORT cr3_ss)
{
    __asm
    {                               //        |     |
        push dword ptr [ESP + 0xC]; // ss     |  eip|<- stack pointer before iretd 
        push dword ptr [ESP + 0xC]; // esp    |   cs|
        push dword ptr [ESP + 0xC]; // flags  |flags|
        push            EDX       ; // cs     |   cs|
        push            ECX       ; // eip    |  eip|
                                  ;           -------
        iretd                     ;             top
    }
}
ZarathustrA
  • 3,434
  • 32
  • 28