Page 1 of 2
Entering usermode question
Posted: Sat Feb 07, 2015 5:28 am
by LPeter
Hi!
Well first, hi for everyone on this forum!
I've successfully entered user-mode, however I don't understand every part of it. I've set up my TSS, that's ok. And this is the code which enters usermode:
Code: Select all
cli
mov ax, 0x23
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Now perform the switch
push 0x23
push esp
pushfd
push 0x1b
lea eax, [a]
push eax
iretd
a:
add esp, 4
This part is a huge black-hole for me. I've understood everything so far, except this part. Why do I need to enter like this?
Thank you!
Peter
Re: Entering usermode question
Posted: Sat Feb 07, 2015 5:29 am
by alexfru
Have you tried reading CPU documentation or have you just copied code from somewhere?
Re: Entering usermode question
Posted: Sat Feb 07, 2015 5:40 am
by LPeter
I've read that IRETD needs SS, ESP, EFLAGS, CS, EIP.
And NULL is 0x0, code is 0x8, data is 0x10, user code is 0x18 and user data is 0x20.
Then for example why do I push 0x1b instead of 0x18?
By the way I only search for code if I can't get something to work, then I try to understand my mistakes.
Re: Entering usermode question
Posted: Sat Feb 07, 2015 6:18 am
by Techel
The low 2 bits of a segmentselector in a segment register is the RPL (except in CS where it the the CPL). The RPL overrides the CPL if it is greater than the CPL when accessing a segment by this selector. The RPL must not be less than the CPL, so when in ring 3 the RPL have to be 3 too.
Re: Entering usermode question
Posted: Sat Feb 07, 2015 10:08 am
by LPeter
Roflo wrote:The low 2 bits of a segmentselector in a segment register is the RPL (except in CS where it the the CPL). The RPL overrides the CPL if it is greater than the CPL when accessing a segment by this selector. The RPL must not be less than the CPL, so when in ring 3 the RPL have to be 3 too.
Right, thank you!
Re: Entering usermode question
Posted: Sat Feb 07, 2015 3:20 pm
by alexfru
LPeter wrote:I've read that IRETD needs SS, ESP, EFLAGS, CS, EIP.
And NULL is 0x0, code is 0x8, data is 0x10, user code is 0x18 and user data is 0x20.
Then for example why do I push 0x1b instead of 0x18?
By the way I only search for code if I can't get something to work, then I try to understand my mistakes.
It's hard to understand what's wrong when you clearly don't know what's right.
You may have read about basic GDT setup and about IRET somewhere (tutorials, pieces of someone else's code, etc). However, the question about 0x1b vs 0x18 (and the original question, which wasn't even specific enough to start answering) undoubtedly indicates that you haven't spent enough time or effort or both reading and understanding x86 segmentation as described in CPU manuals (freely downloadable, in case you didn't know).
Re: Entering usermode question
Posted: Sun Feb 08, 2015 8:28 am
by LPeter
alexfru wrote:LPeter wrote:I've read that IRETD needs SS, ESP, EFLAGS, CS, EIP.
And NULL is 0x0, code is 0x8, data is 0x10, user code is 0x18 and user data is 0x20.
Then for example why do I push 0x1b instead of 0x18?
By the way I only search for code if I can't get something to work, then I try to understand my mistakes.
It's hard to understand what's wrong when you clearly don't know what's right.
You may have read about basic GDT setup and about IRET somewhere (tutorials, pieces of someone else's code, etc). However, the question about 0x1b vs 0x18 (and the original question, which wasn't even specific enough to start answering) undoubtedly indicates that you haven't spent enough time or effort or both reading and understanding x86 segmentation as described in CPU manuals (freely downloadable, in case you didn't know).
You are probably right, I didn't read too much of CPU manuals. I'll fix my lack of knowledge.
Re: Entering usermode question
Posted: Sun Feb 08, 2015 9:33 am
by ExeTwezz
LPeter wrote:You are probably right, I didn't read too much of CPU manuals. I'll fix my lack of knowledge.
Andrew Tanenbaum's books are very good.
Re: Entering usermode question
Posted: Sun Feb 08, 2015 11:39 am
by LPeter
ExeTwezz wrote:LPeter wrote:You are probably right, I didn't read too much of CPU manuals. I'll fix my lack of knowledge.
Andrew Tanenbaum's books are very good.
Then I'm lucky, have it on the bookshelf.
Re: Entering usermode question
Posted: Mon Feb 09, 2015 8:20 am
by Waszka
Hi,
I don't want to create another thread about entering user mode but in my case I get immediate GPF when entering user mode.
I have set up GDT entries for user mode and TSS. I wanted to try to enter Ring 3 with interrupts disabled (just to be sure I can enter it).
Code: Select all
asm(".intel_syntax noprefix\n\t"
"cli \n"
"mov ax, 0x23 \n"
"mov ds, ax \n"
"mov es, ax \n"
"mov fs, ax \n"
"mov gs, ax \n"
"mov ebx, 0x23 \n"
"push ebx \n"
"push esp \n"
"pushfd \n"
"pop eax \n"
"and eax, 0xFFFFFDFF \n" ; turn IF flag to not generate interrupts
"push eax \n"
"mov ebx, 0x1B \n"
"push ebx \n"
"lea eax, [a] \n"
"push eax \n"
"iretd \n"
"a: \n"
"jmp a \n" ; infinite loop
"add esp, 4 \n"
"xor eax, eax \n"
"lea ebx, [testStr] \n"
"int 0x80 \n"
".att_syntax prefix");
However I get:
Code: Select all
00046662829i[CPU0 ] CPU is in protected mode (active)
00046662829i[CPU0 ] CS.mode = 32 bit
00046662829i[CPU0 ] SS.mode = 32 bit
00046662829i[CPU0 ] EFER = 0x00000000
00046662829i[CPU0 ] | EAX=c0006fbd EBX=0000001b ECX=000004b0 EDX=c000b174
00046662829i[CPU0 ] | ESP=c02ff838 EBP=c0300000 ESI=00000010 EDI=c02ffe10
00046662829i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00046662829i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00046662829i[CPU0 ] | CS:001b( 0003| 0| 3) 00000000 ffffffff 1 1
00046662829i[CPU0 ] | DS:0023( 0004| 0| 3) 00000000 ffffffff 1 1
00046662829i[CPU0 ] | SS:0023( 0004| 0| 3) 00000000 ffffffff 1 1
00046662829i[CPU0 ] | ES:0023( 0004| 0| 3) 00000000 ffffffff 1 1
00046662829i[CPU0 ] | FS:0023( 0004| 0| 3) 00000000 ffffffff 1 1
00046662829i[CPU0 ] | GS:0023( 0004| 0| 3) 00000000 ffffffff 1 1
00046662829i[CPU0 ] | EIP=c0006fbd (c0006fbd)
00046662829i[CPU0 ] | CR0=0xe0000011 CR2=0xfffffffc
00046662829i[CPU0 ] | CR3=0x00132000 CR4=0x00000000
(0).[46662829] [0x0000000000406fbd] 001b:00000000c0006fbd (unk. ctxt): jmp .-2 (0xc0006fbd) ; ebfe
00046662829e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting
00046662829i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00046662829i[CPU0 ] cpu hardware reset
As you can see I have good RPL and all segments point to GDT entries for user mode.
What could cause GPF here? Or maybe I should ask: how can I check GPF error?
Bochs resets the machine after fault and I can't access registers prior to error :/
Re: Entering usermode question
Posted: Mon Feb 09, 2015 8:32 am
by Bender
I don't think "3rd (14)" is a GPF; it's rather a PF (page fault).
As for debugging with Bochs, you should compile it with certain options, you can find how to use it here:
http://bochs.sourceforge.net/doc/docboo ... ugger.html
Re: Entering usermode question
Posted: Mon Feb 09, 2015 8:39 am
by Waszka
Oh man....
Thanks, I forgot to allow pages to be user accessible
EDIT: So it works but only if I disable IF. After enabling it I get this error again...
Re: Entering usermode question
Posted: Mon Feb 09, 2015 9:28 am
by Combuster
That means your TSS is either nowhere, or hasn't been filled out with the proper items.
Re: Entering usermode question
Posted: Mon Feb 09, 2015 9:45 am
by Waszka
Combuster wrote:That means your TSS is either nowhere, or hasn't been filled out with the proper items.
Thanks for the answer.
TSS is there but I guess there can be some errors with values inside it. I'll check that.
Code: Select all
<bochs:2> info gdt
Global Descriptor Table (base=0x00000000c000c9a0, limit=47):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x03]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x05]=32-Bit TSS (Busy) at 0xc000c900, length 0x0c968
<bochs:3> info gdt 5
Global Descriptor Table (base=0x00000000c000c9a0, limit=47):
GDT[0x05]=32-Bit TSS (Busy) at 0xc000c900, length 0x0c968
Re: Entering usermode question
Posted: Mon Feb 09, 2015 9:54 am
by ExeTwezz
Waszka wrote:Thanks for the answer.
TSS is there but I guess there can be some errors with values inside it. I'll check that.
You can use
to check the TSS fields.