ionescu007/SimpleVisor

ShvUtilConvertGdtEntry confusion

Closed this issue · 1 comments

I'm quite new to segmentation, so please bare with me.

To get a segment descriptor entry from GDT we have to access the GDT like an array. Each entry in the GDT is 8 bytes, according to the Intel SDM. To my understanding we can therefore access the GDT like:

PSEGMENT_DESCRIPTOR32 Table = ( PSEGMENT_DESCRIPTOR32 )GdtBase;
PSEGMENT_DESCRIPTOR32 Segment = &GdtBase[ Selector.Index ];

Or, what this is equivalent to:

UINTPTR GdtBase = ..;
PSEGMENT_DESCRIPTOR32 Segment;
Segment = ( PSEGMENT_DESCRIPTOR32 )( GdtBase + ( Selector.Index * 8 ) );

Now, while learning, I read the source to a bunch of different hypervisors. Specifically - Gbhv. Gbhv gets segment descriptors from GDT using the exact method above.
https://github.com/Gbps/gbhv/blob/master/gbhv/vmx.c#L178

OsSegmentDescriptor = (PSEGMENT_DESCRIPTOR_64)(((UINT64)GdtRegister.BaseAddress) + (SegmentSelector.Index << 3));

The bitshift to the left by 3 is the same as multiplication by 8, so this is basically exactly the same as the code I wrote above. However, you do it completely differently in SimpleVisor, and I'm very confused as to why.

https://github.com/ionescu007/SimpleVisor/blob/master/shvutil.c#L50

gdtEntry = (PKGDTENTRY64)((uintptr_t)GdtBase + (Selector & ~RPL_MASK));

I understand the Selector & ~RPL_MASK part. You're masking away Rpl & Table bits to extract the index from the selector. But you are not multiplying it by the size of a descriptor (8). Since you're casting GdtBase to a uintptr_t - an integer, this is using integer arithmetic (duh), so it's not accessing the entry in the GDT properly. I'm super confused, because I've personally ran SimpleVisor in the past on both a VMware guest, and on my host system - and it worked. Why? Am I missing something, or is this simply a bug?

Hi!

The answer is simple -- those other sources use the selector index (which is kind of odd).

The code in ShvUtilConvertGdtEntry uses the selector itself. The selector is an offset. So you add the offset to the table base.

I hope this helps!