OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 11:02 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Global Descriptor Table location
PostPosted: Thu Jan 21, 2016 9:05 am 
Offline

Joined: Thu Jan 21, 2016 4:37 am
Posts: 2
I'm confused with the location of the Global Descriptor Table (GDT). According to Intel Manuals from i386 to earlier ones, the GDTR register contains a base address of the GDT table which is pretended to be a linear address. Following Intel conventions, linear addresses are subject to paging.

Nevertheless, I'm wondering which address space is considered. Ring 3 (user-land) programs are perfectly allowed to modify some segment selectors (ES for example). This modification should trigger the processor to load segment descriptor from corresponding entry in the GDT which base address is computed using the linear address given by the GDTR register.

Because linear address are subject to paging, I understand from Intel manuals, that segment descriptor loads go through the memory paging of current process. Because Linux certainly doesn't want to expose the GDT structure to user-land programs, I thought that it somehow managed to introduce a hole in the address space of user-land processes; preventing these processes to read the GDT, while allowing the processor to read it for segment reloads.

I checked by using the following code which showed I'm completely wrong about the GDTR's base linear address.

Code:
int
main()
{
  struct
  {
    uint16_t  pad;
    uint16_t  size;
    uintptr_t base;
  } gdt_info;

  __asm__ volatile ("sgdt %0" : "=m" (gdt_info.size) );

  void* try_mmgdt = (void*)( gdt_info.base & ~0xfff );
  void* chk_mmgdt = mmap(try_mmgdt, 0x4000, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

  std::cout << "gdt size: \t" << std::dec << gdt_info.size << std::endl;
  std::cout << "gdt base: \t" << std::hex << gdt_info.base << std::endl;
  std::cout << "mmgdt try:\t" << std::hex << uintptr_t(try_mmgdt) << std::endl;
  std::cout << "mmgdt chk:\t" << std::hex << uintptr_t(chk_mmgdt) << std::endl;

  return 0;
}


The program output (i386-compiled) on my machine is:

Code:
gdt size:       127
gdt base:       1dd89000
mmgdt try:      1dd89000
mmgdt chk:      1dd89000


The linear addresses of GDT entries and linear addresses of the mmap chunk perfectly overlap. Nevertheless the mmap chunk has obviously no relation with the GDT.

So my question finally is: which Intel/linux mechanism makes the linear address of the GDTR and the linear address of the current process point to different memory region ?


Top
 Profile  
 
 Post subject: Re: Global Descriptor Table location
PostPosted: Thu Jan 21, 2016 3:56 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

yushill wrote:
Because linear address are subject to paging, I understand from Intel manuals, that segment descriptor loads go through the memory paging of current process. Because Linux certainly doesn't want to expose the GDT structure to user-land programs, I thought that it somehow managed to introduce a hole in the address space of user-land processes; preventing these processes to read the GDT, while allowing the processor to read it for segment reloads.


When software accesses something the CPU asks itself "is this software allowed to access it?" (which is effected by CPL, etc). When the CPU accesses something itself (e.g. GDT table lookups, IDT table lookups, setting the accessed and dirty flags in page table entries, etc) the CPU asks itself "am I allowed to access it" instead (which has nothing to do with CPL).

When the CPU is accessing the GDT (for whatever reason), the CPU only checks GDT limit - an OS doesn't need to ensure the GDT can be accessed at CPL=3.


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.


Top
 Profile  
 
 Post subject: Re: Global Descriptor Table location
PostPosted: Thu Jan 21, 2016 5:14 pm 
Offline
Member
Member

Joined: Thu Mar 25, 2010 11:26 pm
Posts: 1801
Location: Melbourne, Australia
Firstly you really should use __attribute__ ((packed)) on the struct especially in 64 bit land. I would not trust the result until you do.

I would expect to see something like the following on a 64 bit kernel

Code:
gdt size:    127
gdt base:    ffff88021fd09000
mmgdt try:   0xffff88021fd09000
mmgdt chk:   0x7fe7dcead000
I would expect you to see that the gdt base is actually in the kernel memory area near the top of memory and then I would expect mmap to refuse to map that area and place your request somewhere in user space. That's what happens on my OS ;)

_________________
If a trainstation is where trains stop, what is a workstation ?


Top
 Profile  
 
 Post subject: Re: Global Descriptor Table location
PostPosted: Fri Jan 22, 2016 7:04 am 
Offline

Joined: Thu Jan 21, 2016 4:37 am
Posts: 2
Quote:
Firstly you really should use __attribute__ ((packed)) on the struct especially in 64 bit land. I would not trust the result until you do.


Your perfectly right about the packed attribute, I definitly should have used it. Nevertheless I compiled all this stuff with proper -m32 flags and that led to the correct offset (byte 0-1 for the limit and 2-5 for the base, I've checked the asm).

*But*, and this is where your answer enlightened me :D. Though my code is running in 32 bits it's not using legacy 32 bit mode but compat mode.
Thus, current process' linear addresses are 32 bits but GDTR's linear address is 64bits (even in compat mode).
Using LGDT in compat mode only gives you the lower 32bits of the true GDTR linear address.

Edit: @Brendan: regarding the "Protection" part, you're right, during its lookup the processor doesn't check access rights as it would do for software, but my confusion was rather on the "Translation" part. By the way, its one of these few differences between "legacy 32-bits protected mode" and "32-bits compat-mode" that I'm still discovering...

Thanks for helping me understand that.

Y.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Yahoo [Bot] and 61 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group