Page 1 of 2
AT&T syntax
Posted: Tue Aug 30, 2005 11:33 am
by DruG5t0r3
I'm moving my code to AT&T...(arghhh) and there is a few things I might need help for...
first thing is I'm trying to do a far call to a ring 3 code segment from ring 0.
Something like call 0x08:offset in intel syntax.
What would it be in AT&T?
Re:AT&T syntax
Posted: Tue Aug 30, 2005 12:03 pm
by Guest
I believe something along the lines of:
Re:AT&T syntax
Posted: Tue Aug 30, 2005 12:45 pm
by DruG5t0r3
Okay...I'm just about to run crazy here...
I'm trying to ljmp to some ring 3 code from ring 0 code.
with something like this
__asm__ ("ljmp $0x1b, $ring_3_code");
0x1b is actually 0x18 + 3 for the RPL, Is that right?
I get a General Protection Fault, it doesn't actually even jmp to that code.
If I change this value from 0x1b to 0x08 which is my ring 0 code segment. Well everything is fine.
Re:AT&T syntax
Posted: Tue Aug 30, 2005 5:15 pm
by Simon
If 0x18 is your user mode code segment then yes,you need to add 3. It might be that you can't switch priviledge levels without using a TSS or 'iret'ing to the code,that's the only explanation I can think of as those are the only ways to load SS at the same time.
Re:AT&T syntax
Posted: Wed Aug 31, 2005 9:04 am
by DruG5t0r3
I do have a TSS, but there is no SS and ESP for ring 3 code in it right? Only for privilege levels < 3.
I thought that the only time you'd need the TSS for is when you switched form level 3 code to anything lower.
Re:AT&T syntax
Posted: Wed Aug 31, 2005 1:01 pm
by DruG5t0r3
Help anyone? I'm really stuck on this one.
Thanks.
Re:AT&T syntax
Posted: Wed Aug 31, 2005 2:32 pm
by DruG5t0r3
Here is my source code, keep in mind i'm simply trying to switch to ring 3 code
Code: Select all
void gdt_set_gate(int num, unsigned long base, unsigned long limit,
unsigned char access, unsigned char gran)
{
memset(&gdt[num], 0, sizeof(struct gdtr));
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].gran = ((limit >> 16) & 0x0F);
gdt[num].gran |= (gran & 0xF0);
gdt[num].access = access;
}
// Main gdt.c function called from kernel.c
// Will install all the global descriptor tables and the Task-State Segment.
void gdt_install()
{
unsigned short tss_val;
gdt_set_gate(NULL_SEG, 0, 0, 0, 0);
// Code Descriptor, 4gb limit, 0 base
gdt_set_gate(CODE0_SEG, 0, 0xFFFFFFFF, 0x9A, 0xCF);
// Same thing for data segment.
gdt_set_gate(DATA0_SEG, 0, 0xFFFFFFFF, 0x92, 0xCF);
// base ring 3 code segment
gdt_set_gate(CODE3_SEG, 0, 0xFFFFFFFF, 0xFA, 0xCF);
// base ring 3 data segment
gdt_set_gate(DATA3_SEG, 0, 0xFFFFFFFF, 0xF2, 0xCF);
// Main TSS Descriptor
gdt_set_gate(TSS_SEG, (unsigned long)&kernel_tss, 0x67, 0xE9, 0x80);
Now this is my "test code"
Code: Select all
void ring3_code() {
for(;;);
}
void switch_to() {
__asm__ __volatile__ ("ljmp $0x1b,$ring3_code");
}
If I change 0x1b to 0x08 which is my code 0 ring segment , NOOo problem. But with the above, General Protection Fault. Hellpp
Re:AT&T syntax
Posted: Wed Aug 31, 2005 6:43 pm
by AR
Without a TSS the system will explode when it tries to load SS0 when an interrupt occurs in Ring 3. The obvious problem there is that your task is C code and therefore probably disassembles as:
Code: Select all
push %ebp
mov %esp, %ebp
1:
jmp 1b
pop %ebp
ret
The push at the start attempts to write to the stack which is still Ring0 (DPL < CPL) which will throw a GPF. If this is actually the case then you will need to load the Ring3 stack before switching or write the task in assembly.
Re:AT&T syntax
Posted: Wed Aug 31, 2005 6:47 pm
by DruG5t0r3
nah, it GP faults when executing the jmp, it doesnt actually jmp.
and the IF flag is cleared anyway
Re:AT&T syntax
Posted: Wed Aug 31, 2005 7:29 pm
by AR
The only other thing that comes to mind is that you aren't allowed to jump/call DPL/RPL > CPL, I don't think this is the case (I don't have the docs with me) but you may want to try using IRET to switch anyway.
Re:AT&T syntax
Posted: Wed Aug 31, 2005 7:47 pm
by DruG5t0r3
I have tried the IRET equivalent and it does the same error.
I have found something in the Intel Manual Though...and it reads
Execution cannot be transferred by a call or a jump to a less-privilged (nummerically higher privilege level) code segment, regardless of whether the target segment is a conforming or nonconforming code segment. Attempting such an execution will result in a general-protection exception.
Interesting...sounds like you can't jmp from more priviledged segment to a less one. I thought it was possible, at least logicaly possible, but, as always, the specs aren't always what you think they should be.
So in the end, what would be the only way to switch over? Through a call gate?
Re:AT&T syntax
Posted: Wed Aug 31, 2005 11:39 pm
by Brendan
Hi,
DruG5t0r3 wrote:So in the end, what would be the only way to switch over? Through a call gate?
Pretend to do a return from an interrupt (IRET) or a return from a call gate (RETF).
Why didn't "IRET" work?
Cheers,
Brendan
Re:AT&T syntax
Posted: Thu Sep 01, 2005 5:28 am
by DruG5t0r3
Exact same error
Code: Select all
void ring3_code() {
for(;;);
}
void switch_to() {
__asm__ __volatile__ ("pushfl; \
pushl $0x1b; \
pushl %0; \
iret"::"r"((unsigned int)ring3_code));
}
But if I change the $0x1b value to 0x08, again it works.
As I said, with $0x1b, it doesn't actually even jump, it GP faults while executing the iret.
Re:AT&T syntax
Posted: Thu Sep 01, 2005 6:24 am
by Brendan
Hi,
DruG5t0r3 wrote:
Exact same error
Code: Select all
__asm__ __volatile__ ("pushfl; \
pushl $0x1b; \
pushl %0; \
iret"::"r"((unsigned int)ring3_code));
A slightly different error, with the same exception!
For an interrupt, the CPU pops EIP, then CS, then EFLAGS, so for your code what does it pop for EFLAGS?
Cheers,
Brendan
Re:AT&T syntax
Posted: Thu Sep 01, 2005 6:34 am
by DruG5t0r3
"pushfl"
Doesn't that push the EFLAGS?