- %fs = 0x2B, which is a dummy GDT descriptor that I cloned from my ring3 DS descriptor
- Long mode.
I'm using the MSR method with MSRID = 0xC0000100 to change FS.base (as described in the AMD manual). I'm getting a page fault on address 0xFFFFFFFFFFFFFFFC, which is -4(0). This is the disassembly of the faulting code (in userspace):
Code: Select all
2000ab9: 64 48 8b 04 25 00 00 mov %fs:0x0,%rax
2000ac0: 00 00
2000ac2: 48 8d 80 fc ff ff ff lea -0x4(%rax),%rax
2000ac9: c7 00 00 00 00 00 movl $0x0,(%rax)
2000acf: 48 83 c4 08 add $0x8,%rsp
Basically, since movl $0x0, (%rax) page faults, then lea -0x4(%rax) must be loading 0xFFFFFFFFFFFFFFFC, therefore %fs:0x0 must be 0.
Here's how I'm changing %fs:
Code: Select all
uint32_t low = tlsptr & 0xFFFFFFFF;
uint32_t high = tlsptr >> 32;
asm volatile(
"mov $0x2B, %%bx \n\t"
"mov %%bx, %%fs \n\t"
"movl $0xC0000100, %%ecx \n\t"
"movl %[lo], %%eax \n\t"
"movl %[hi], %%edx \n\t"
"wrmsr \n\t"
:: [lo]"g"(low), [hi]"g"(high) : "memory", "rax", "rbx", "rcx", "rdx");
And finally, here's the GDT entry for 0x28:
Code: Select all
GDTFS:
.word 0xFFFF // Limit (low)
.word 0 // Base (low)
.byte 0 // Base (middle)
.byte 0xF2 // Access
.byte 0xAF // Granularity (4) / Limit (high) (4)
.byte 0 // Base (high)
This has literally been bugging me for more than a few hours now, so any help is appreciated, thanks!