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
Bender wrote: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
Oh man.... #-o
Thanks, I forgot to allow pages to be user accessible :P

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

Code: Select all

info tss
to check the TSS fields.