obviously flawed.length 0x0c968
Entering usermode question
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Entering usermode question
Re: Entering usermode question
Yeah that looks odd...Combuster wrote:obviously flawed.length 0x0c968
But info tss looks good:
Code: Select all
<bochs:3> info tss
tr:s=0x2b, base=0x00000000c001d6c0, valid=1
ss:esp(0): 0x0010:0xc02ff844
ss:esp(1): 0x0000:0x00000000
ss:esp(2): 0x0000:0x00000000
cr3: 0x00000000
eip: 0x00000000
eflags: 0x00000000
cs: 0x000b ds: 0x0013 ss: 0x0013
es: 0x0013 fs: 0x0013 gs: 0x0013
eax: 0x00000000 ebx: 0x00000000 ecx: 0x00000000 edx: 0x00000000
esi: 0x00000000 edi: 0x00000000 ebp: 0x00000000 esp: 0x00000000
ldt: 0x0000
i/o map: 0x0000
Code: Select all
Page fault! (read-only user-mode) at *address*
I install my tss segment as follows:
Code: Select all
gdt_set_descriptor (idx, base, base + sizeof (struct tss_entry),
I86_GDT_DESC_ACCESS|I86_GDT_DESC_EXEC_CODE|I86_GDT_DESC_DPL|I86_GDT_DESC_MEMORY,
0);
I don't know why this length is so big...
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Entering usermode question
Spot the big numberbase + sizeof (struct tss_entry)
Re: Entering usermode question
Oh my...Combuster wrote:Spot the big numberbase + sizeof (struct tss_entry)
Thanks... Such a stupid mistake...
EDIT:
Thanks Combuster for such fast and helpful responses. I really appreciate your help
Re: Entering usermode question
One more question (I hope so) about whole TSS-thing.
I don't know if I understand everything correctly...
When I enter user mode I fill TSS with kernel ss and esp and make TSS user-accessible so that I can come back to kernel land when switch occurs.
And I know that such switch occurs when interrupt/exception is raised. But can such switch occur in any other situation?
After interrupt is raised processor loads ss and esp. I assume it also pushes all user mode info on stack (like in any other interrupt routine) so that with iretd it gets to user land again.
But how can I get for example to ring 1 or ring 2 (in TSS there are appropriate fields for this)?
Also how processor knows what is value of CS for ring0? EDIT: (is it this TSS.cs = 0x0B? So does it mean that CPU makes switch from 0x0B -> 0x08 (changes RPL automatically?))
I don't know if I understand everything correctly...
When I enter user mode I fill TSS with kernel ss and esp and make TSS user-accessible so that I can come back to kernel land when switch occurs.
And I know that such switch occurs when interrupt/exception is raised. But can such switch occur in any other situation?
After interrupt is raised processor loads ss and esp. I assume it also pushes all user mode info on stack (like in any other interrupt routine) so that with iretd it gets to user land again.
But how can I get for example to ring 1 or ring 2 (in TSS there are appropriate fields for this)?
Also how processor knows what is value of CS for ring0? EDIT: (is it this TSS.cs = 0x0B? So does it mean that CPU makes switch from 0x0B -> 0x08 (changes RPL automatically?))
Re: Entering usermode question
When an interrupt occurres, the processor loads the selector (bits 16-31) from the corresponding IDT-Entry. To enter user mode (i.e. ring 1-3), IRETD (software multitasking) or a jump to a tss segment (hardware multitasking) can be used. IRETD takes some stuff (EFLAGS, ESP, SS..) and CS from the stack, which holds the CPL. Such privilege changes only occurres when a interrupt/exception happens or a call gate is invoked or by sysenter.
Re: Entering usermode question
Ok thanks but what happens when I invoke for exampleRoflo wrote:When an interrupt occurres, the processor loads the selector (bits 16-31) from the corresponding IDT-Entry. To enter user mode (i.e. ring 1-3), IRETD (software multitasking) or a jump to a tss segment (hardware multitasking) can be used. IRETD takes some stuff (EFLAGS, ESP, SS..) and CS from the stack, which holds the CPL. Such privilege changes only occurres when a interrupt/exception happens or a call gate is invoked or by sysenter.
Code: Select all
int 0x80
And what happens when I invoke
Code: Select all
int 14
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Entering usermode question
Basic stack safety requires that whenever you change from ring 3 to ring 0, SS and ESP are not trusted for use. Therefore, the CPU loads them from the TSS whenever that scenario occurs.
Re: Entering usermode question
So when I'm in user mode and use for example int 0x80 (syscall interrupt) my processor checks if I have rights to call it (in IDT table) and if I have then it backs to ring 0 (using TSS) pushing all registers so it can come back to ring 3 after interrupt right?
If I don't have right to call interrupt the GPF is raised and kernel falls back to ring 0 again using TSS.
Do I have it right now?
EDIT:
Ok I think I know what is going on right now. I've read http://www.jamesmolloy.co.uk/tutorial_h ... 0Mode.html again just to be sure.
I'm just confused about this part of code:
When I set cs to 0x08 and other segments to 0x10 I don't get any error...
If I don't have right to call interrupt the GPF is raised and kernel falls back to ring 0 again using TSS.
Do I have it right now?
EDIT:
Ok I think I know what is going on right now. I've read http://www.jamesmolloy.co.uk/tutorial_h ... 0Mode.html again just to be sure.
I'm just confused about this part of code:
Code: Select all
// Here we set the cs, ss, ds, es, fs and gs entries in the TSS. These specify what
// segments should be loaded when the processor switches to kernel mode. Therefore
// they are just our normal kernel code/data segments - 0x08 and 0x10 respectively,
// but with the last two bits set, making 0x0b and 0x13. The setting of these bits
// sets the RPL (requested privilege level) to 3, meaning that this TSS can be used
// to switch to kernel mode from ring 3.
tss_entry.cs = 0x0b;
tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13;
Re: Entering usermode question
Hi,
When switching from CPL=3 to CPL=0; the CPU only loads SS and ESP from the "SS0" and "ESP0" fields of the TSS. It does not touch anything else in the TSS. It also loads CS and EIP from the IDT entry (and not the TSS). The old values of SS, ESP, CS and EIP (and EFLAGS) are pushed onto the new stack. All other registers are not saved or loaded (by the CPU) at all.
When returning from CPL=0 to CPL=3 (e.g. "iret") the CPU loads the original values of SS, ESP, CS, EIP and EFLAGS from the stack. The TSS is not used for this at all. All other registers are not saved or loaded (by the CPU) at all.
Cheers,
Brendan
You're confused because that part of the tutorial is a mostly wrong.Waszka wrote:I'm just confused about this part of code:Code: Select all
// Here we set the cs, ss, ds, es, fs and gs entries in the TSS. These specify what // segments should be loaded when the processor switches to kernel mode. Therefore // they are just our normal kernel code/data segments - 0x08 and 0x10 respectively, // but with the last two bits set, making 0x0b and 0x13. The setting of these bits // sets the RPL (requested privilege level) to 3, meaning that this TSS can be used // to switch to kernel mode from ring 3. tss_entry.cs = 0x0b; tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13;
When switching from CPL=3 to CPL=0; the CPU only loads SS and ESP from the "SS0" and "ESP0" fields of the TSS. It does not touch anything else in the TSS. It also loads CS and EIP from the IDT entry (and not the TSS). The old values of SS, ESP, CS and EIP (and EFLAGS) are pushed onto the new stack. All other registers are not saved or loaded (by the CPU) at all.
When returning from CPL=0 to CPL=3 (e.g. "iret") the CPU loads the original values of SS, ESP, CS, EIP and EFLAGS from the stack. The TSS is not used for this at all. All other registers are not saved or loaded (by the CPU) at all.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.