Page 1 of 1

IRET and Ring 3

Posted: Sun Feb 19, 2006 3:57 am
by spix
Hi Again

I am trying to make my ring 3 application use a syscall to write to the screen. My ISR for the syscall (which is a trap) calls my screen writing function and it writes on the screen. This works. However, when I IRET from the syscall, I get a pagefault because the eip = 0x0. If I dump the stack while in the ISR it has the correct eip. When the IRET happens it is nowhere to be found.

I read in the AMD docs that when IRET to a lower privilage level a stack switch occurs. Does it switch stacks before getting the eip?

I am a bit lost. My Syscall ISR looks like this:

Code: Select all

syscall_irq:
   push byte 0

   push byte 48

   jmp irq_common_stub


extern irq_handler

irq_common_stub:
   cld
   pushad
   push ds
   push es
   push fs
   push gs

   mov ax, 0x10
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   push esp

   call irq_handler

   pop esp

   pop gs   
   pop fs
   pop es
   pop ds
   popad

   add esp, 8

   iret
Also I am resetting the interrupt controller when I leave the ISR, do I need to do that with a software irq?

Thanks
Andrew

Re:IRET and Ring 3

Posted: Sun Feb 19, 2006 4:23 am
by JoeKayzA
Why do you add '8' to esp before you leave the ISR? At the entry, you are pushing two bytes, '0' and '48', so you should rather add '2' to esp to discard them. I suspect you confused bytes and dwords here, two dwords would have a length of 8...

cheers Joe

Re:IRET and Ring 3

Posted: Sun Feb 19, 2006 4:30 am
by Pype.Clicker
JoeKayzA wrote: Why do you add '8' to esp before you leave the ISR? At the entry, you are pushing two bytes, '0' and '48', so you should rather add '2' to esp to discard them.
<alarm lights="red" siren="on">
beware... "push byte 12" doesn't tell the stack "advance stack pointer by one byte and store "12". It says "push value 12 on the stack and please encode the value as an immediate byte in the instruction stream because i don't need you to waste 32 bits here to store it".
</alarm>

The stack _always_ always grows and shrink by 32-bit value increments in protected mode. Check back your manuals or run the code in an emulator and compare esp before and after the two "push byte XX" commands and you'll see "add esp,8" is the proper thing to do...

and btw, it could have been written "add esp, byte 8" for the same reason :P

Re:IRET and Ring 3

Posted: Sun Feb 19, 2006 4:38 am
by Pype.Clicker
First, i would replace "pop esp" by "add esp,4" if i were you. I don't see any good reason to modify the stack pointer here unless you're trying to do stack-switching here ...

then, if the problem can be reproduced in the bochs, i suggest you break at "add esp,4", compare your stack with the stack when you enter the ISR and trace instructions untill (and past) you "IRET" ... that should give you more weapons to sneak the bug.

Re:IRET and Ring 3

Posted: Sun Feb 19, 2006 7:35 am
by distantvoices
I wouldn't do this push/pop esp stuff around the call_irqhandler.

This is already done with INT/IRET - if you switch privilege levels, so it's kinda needless. You know, the esp/ss pair which is pushed on the stackupon INT, gets popped back upon IRET - and could be from a completely different task in case a task switch occurs.

just my 2 ?-cent.

Re:IRET and Ring 3

Posted: Sun Feb 19, 2006 12:13 pm
by JoeKayzA
Pype.Clicker wrote: The stack _always_ always grows and shrink by 32-bit value increments in protected mode. Check back your manuals or run the code in an emulator and compare esp before and after the two "push byte XX" commands and you'll see "add esp,8" is the proper thing to do...
Strange, I never really noticed that, but you are right: Pushing a single byte doesn't work because there isn't even a 'pushb' instruction (in AT&T synthax) 8) . So when you tell nasm that the operand size is one byte, it silently inserts a 'pushl' instruction instead. There is a seperate instruction for pushing and popping 16 bit words however, therefore it surprised me. OK, just learned another important detail! ;)

Re:IRET and Ring 3

Posted: Sun Feb 19, 2006 6:54 pm
by spix
then, if the problem can be reproduced in the bochs, i suggest you break at "add esp,4", compare your stack with the stack when you enter the ISR and trace instructions untill (and past) you "IRET" ... that should give you more weapons to sneak the bug.
I did this, and it turns out it was a bug in my application.. my kernel was working fine. :-\

Thanks for all the help.