ReactOS 0.4.15-dev-7846-g8ba6c66
ldt.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for ldt.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS NTAPI Ke386GetGdtEntryThread (IN PKTHREAD Thread, IN ULONG Offset, IN PKGDTENTRY Descriptor)
 
VOID KeSetBaseGdtSelector (ULONG Entry, PVOID Base)
 
VOID KeSetGdtSelector (ULONG Entry, ULONG Value1, ULONG Value2)
 
BOOLEAN PspIsDescriptorValid (PLDT_ENTRY ldt_entry)
 
NTSTATUS NTAPI NtSetLdtEntries (ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2)
 

Variables

static KSPIN_LOCK LdtLock
 
static KSPIN_LOCK GdtLock
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file ldt.c.

Function Documentation

◆ Ke386GetGdtEntryThread()

NTSTATUS NTAPI Ke386GetGdtEntryThread ( IN PKTHREAD  Thread,
IN ULONG  Offset,
IN PKGDTENTRY  Descriptor 
)

Definition at line 26 of file ldt.c.

29{
30 /* Make sure the offset isn't outside the allowed range */
31 if (Offset >= (KGDT_NUMBER * sizeof(KGDTENTRY)))
32 {
33 /* It is, fail */
35 }
36
37 /* Check if this is the LDT selector */
38 if (Offset == KGDT_LDT)
39 {
40 /* Get it from the thread's process */
42 &Thread->Process->LdtDescriptor,
43 sizeof(KGDTENTRY));
44 }
45 else
46 {
47 /* Get the descriptor entry from the GDT */
49 (PVOID)(((ULONG_PTR)KeGetPcr()->GDT) + Offset),
50 sizeof(KGDTENTRY));
51
52 /* Check if this is the TEB selector */
53 if (Offset == KGDT_R3_TEB)
54 {
55 /*
56 * Make sure we set the correct base for this thread. This is per
57 * process and is set in the GDT on context switch, so it might not
58 * be correct for the thread specified.
59 */
60 Descriptor->BaseLow =
61 (USHORT)((ULONG_PTR)(Thread->Teb) & 0xFFFF);
62 Descriptor->HighWord.Bytes.BaseMid =
63 (UCHAR)((ULONG_PTR)(Thread->Teb) >> 16);
64 Descriptor->HighWord.Bytes.BaseHi =
65 (UCHAR)((ULONG_PTR)(Thread->Teb) >> 24);
66 }
67 }
68
69 /* Success */
70 return STATUS_SUCCESS;
71}
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define KGDT_R3_TEB
Definition: ketypes.h:129
#define KeGetPcr()
Definition: ketypes.h:81
#define KGDT_NUMBER
Definition: ketypes.h:138
#define KGDT_LDT
Definition: ketypes.h:131
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by PspQueryDescriptorThread().

◆ KeSetBaseGdtSelector()

VOID KeSetBaseGdtSelector ( ULONG  Entry,
PVOID  Base 
)

Definition at line 74 of file ldt.c.

76{
77 KIRQL oldIrql;
78 PUSHORT Gdt;
79
80 DPRINT("KeSetBaseGdtSelector(Entry %x, Base %p)\n", Entry, Base);
81
82 KeAcquireSpinLock(&GdtLock, &oldIrql);
83
84 Gdt = (PUSHORT)KeGetPcr()->GDT;
85 Entry = (Entry & (~0x3)) / 2;
86
87 Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);
88
89 Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
90 Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] |
91 ((((ULONG)Base) & 0xff0000) >> 16));
92
93 Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
94 Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] |
95 ((((ULONG)Base) & 0xff000000) >> 16));
96
97 DPRINT("%x %x %x %x\n",
98 Gdt[Entry + 0],
99 Gdt[Entry + 1],
100 Gdt[Entry + 2],
101 Gdt[Entry + 3]);
102
103 KeReleaseSpinLock(&GdtLock, oldIrql);
104}
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
static KSPIN_LOCK GdtLock
Definition: ldt.c:20
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
#define DPRINT
Definition: sndvol32.h:71
base of all file and directory entries
Definition: entries.h:83
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59

◆ KeSetGdtSelector()

VOID KeSetGdtSelector ( ULONG  Entry,
ULONG  Value1,
ULONG  Value2 
)

Definition at line 107 of file ldt.c.

110{
111 KIRQL oldIrql;
112 PULONG Gdt;
113
114 DPRINT("KeSetGdtSelector(Entry %x, Value1 %x, Value2 %x)\n",
115 Entry, Value1, Value2);
116
117 KeAcquireSpinLock(&GdtLock, &oldIrql);
118
119 Gdt = (PULONG) KeGetPcr()->GDT;
120 Entry = (Entry & (~0x3)) / 4;
121
122 Gdt[Entry] = Value1;
123 Gdt[Entry + 1] = Value2;
124
125 DPRINT("%x %x\n",
126 Gdt[Entry + 0],
127 Gdt[Entry + 1]);
128
129 KeReleaseSpinLock(&GdtLock, oldIrql);
130}
uint32_t * PULONG
Definition: typedefs.h:59

Referenced by KiSwapContextExit(), KiSwapProcess(), and NtSetLdtEntries().

◆ NtSetLdtEntries()

NTSTATUS NTAPI NtSetLdtEntries ( ULONG  Selector1,
LDT_ENTRY  LdtEntry1,
ULONG  Selector2,
LDT_ENTRY  LdtEntry2 
)

Definition at line 184 of file ldt.c.

188{
189 KIRQL oldIrql;
190 ULONG NewLdtSize = sizeof(LDT_ENTRY);
191 PUSHORT LdtDescriptor;
192 ULONG LdtBase;
193 ULONG LdtLimit;
194
195 if((Selector1 & ~0xffff) || (Selector2 & ~0xffff)) return STATUS_INVALID_LDT_DESCRIPTOR;
196
197 Selector1 &= ~0x7;
198 Selector2 &= ~0x7;
199
200 if((Selector1 && !PspIsDescriptorValid(&LdtEntry1)) ||
201 (Selector2 && !PspIsDescriptorValid(&LdtEntry2))) return STATUS_INVALID_LDT_DESCRIPTOR;
202 if(!(Selector1 || Selector2)) return STATUS_SUCCESS;
203
204 NewLdtSize += (Selector1 >= Selector2) ? Selector1 : Selector2;
205
206 KeAcquireSpinLock(&LdtLock, &oldIrql);
207
208 LdtDescriptor = (PUSHORT) &PsGetCurrentProcess()->Pcb.LdtDescriptor;
209 LdtBase = LdtDescriptor[1] |
210 ((LdtDescriptor[2] & 0xff) << 16) |
211 ((LdtDescriptor[3] & ~0xff) << 16);
212 LdtLimit = LdtDescriptor[0] |
213 ((LdtDescriptor[3] & 0xf) << 16);
214
215 if(LdtLimit < (NewLdtSize - 1))
216 {
217 /* allocate new ldt, copy old one there, set gdt ldt entry to new
218 values and load ldtr register and free old ldt */
219
220 ULONG NewLdtBase = (ULONG) ExAllocatePool(NonPagedPool,
221 NewLdtSize);
222
223 if(!NewLdtBase)
224 {
225 KeReleaseSpinLock(&LdtLock, oldIrql);
227 }
228
229 if(LdtBase)
230 {
231 memcpy((PVOID) NewLdtBase, (PVOID) LdtBase, LdtLimit+1);
232 }
233
234 LdtDescriptor[0] = (USHORT)((--NewLdtSize) & 0xffff);
235 LdtDescriptor[1] = (USHORT)(NewLdtBase & 0xffff);
236 LdtDescriptor[2] = (USHORT)(((NewLdtBase & 0xff0000) >> 16) | 0x8200);
237 LdtDescriptor[3] = (USHORT)(((NewLdtSize & 0xf0000) >> 16) |
238 ((NewLdtBase & 0xff000000) >> 16));
239
241 ((PULONG) LdtDescriptor)[0],
242 ((PULONG) LdtDescriptor)[1]);
243
244 Ke386SetLocalDescriptorTable(KGDT_LDT);
245
246 if(LdtBase)
247 {
248 ExFreePool((PVOID) LdtBase);
249 }
250
251 LdtBase = NewLdtBase;
252 }
253
254 if(Selector1)
255 {
256 memcpy((char*)LdtBase + Selector1,
257 &LdtEntry1,
258 sizeof(LDT_ENTRY));
259 }
260
261 if(Selector2)
262 {
263 memcpy((char*)LdtBase + Selector2,
264 &LdtEntry2,
265 sizeof(LDT_ENTRY));
266 }
267
268 KeReleaseSpinLock(&LdtLock, oldIrql);
269 return STATUS_SUCCESS;
270}
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
static KSPIN_LOCK LdtLock
Definition: ldt.c:19
VOID KeSetGdtSelector(ULONG Entry, ULONG Value1, ULONG Value2)
Definition: ldt.c:107
BOOLEAN PspIsDescriptorValid(PLDT_ENTRY ldt_entry)
Definition: ldt.c:132
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define LDT_ENTRY
Definition: ketypes.h:289
#define STATUS_INVALID_LDT_DESCRIPTOR
Definition: ntstatus.h:518
Definition: compat.h:777
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define PsGetCurrentProcess
Definition: psfuncs.h:17

◆ PspIsDescriptorValid()

BOOLEAN PspIsDescriptorValid ( PLDT_ENTRY  ldt_entry)

Definition at line 132 of file ldt.c.

133{
134 ULONG Base, SegLimit;
135 /*
136 Allow invalid descriptors.
137 */
138 if(!ldt_entry->HighWord.Bits.Type &&
139 !ldt_entry->HighWord.Bits.Dpl)
140 return TRUE;
141
142 /* eliminate system descriptors and code segments other than
143 execute and execute/read and DPL<3 descriptors */
144 if(!(ldt_entry->HighWord.Bits.Type & 0x10) ||
145 (ldt_entry->HighWord.Bits.Type & 0x8 &&
146 ldt_entry->HighWord.Bits.Type & 0x4) ||
147 ldt_entry->HighWord.Bits.Dpl != 3 ||
148 ldt_entry->HighWord.Bits.Reserved_0) return FALSE;
149
150 if(!ldt_entry->HighWord.Bits.Pres) return TRUE;
151
152 Base=ldt_entry->BaseLow | (ldt_entry->HighWord.Bytes.BaseMid << 16) |
153 (ldt_entry->HighWord.Bytes.BaseHi << 24);
154
155 SegLimit=ldt_entry->LimitLow |
156 (ldt_entry->HighWord.Bits.LimitHi << 16);
157
158 if(ldt_entry->HighWord.Bits.Type & 0x4)
159 {
160 SegLimit=(ldt_entry->HighWord.Bits.Default_Big) ? -1 : (USHORT)-1;
161
162 } else if(ldt_entry->HighWord.Bits.Granularity)
163 {
164 SegLimit=(SegLimit << 12) | 0xfff;
165 }
166
167 if ((Base + SegLimit > (ULONG_PTR) MmHighestUserAddress) ||
168 (Base > Base+SegLimit))
169 {
170 DPRINT1("WARNING: Windows would mark this descriptor invalid!\n");
171 }
172
173 /*
174 Certain "DOS32" programs expect to be able to create DPMI selectors
175 that wrap the address space. Windows NT does not allow user-created
176 selectors to reach into kernel memory. However, there is no security
177 risk in allowing it; the page table will prevent access anyway.
178 */
179 return (/*(Base + SegLimit > (ULONG_PTR) MmHighestUserAddress) ||
180 (Base > Base+SegLimit) ? FALSE : TRUE*/ TRUE);
181}
#define DPRINT1
Definition: precomp.h:8
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
PVOID MmHighestUserAddress
Definition: rtlcompat.c:29
union _LDT_ENTRY::@358 HighWord
struct _LDT_ENTRY::@358::@360 Bits
WORD LimitLow
Definition: compat.h:778
WORD BaseLow
Definition: compat.h:779
struct _LDT_ENTRY::@358::@359 Bytes

Referenced by NtSetLdtEntries().

Variable Documentation

◆ GdtLock

KSPIN_LOCK GdtLock
static

Definition at line 20 of file ldt.c.

Referenced by KeSetBaseGdtSelector(), and KeSetGdtSelector().

◆ LdtLock

KSPIN_LOCK LdtLock
static

Definition at line 19 of file ldt.c.

Referenced by NtSetLdtEntries().