Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

psldt.c File Reference

#include "psp.h"

Go to the source code of this file.

Defines

#define DESCRIPTOR_GRAN   0x00800000
#define DESCRIPTOR_NP   0x00008000
#define DESCRIPTOR_SYSTEM   0x00001000
#define DESCRIPTOR_CONFORM   0x00001C00
#define DESCRIPTOR_DPL   0x00006000
#define DESCRIPTOR_TYPEDPL   0x00007F00

Functions

PLDT_ENTRY PspCreateLdt (IN PLDT_ENTRY Ldt, IN ULONG Offset, IN ULONG Size, IN ULONG AllocationSize)
BOOLEAN PspIsDescriptorValid (IN PLDT_ENTRY Descriptor)
NTSTATUS PspLdtInitialize ()
NTSTATUS PspQueryLdtInformation (IN PEPROCESS Process, OUT PPROCESS_LDT_INFORMATION LdtInformation, IN ULONG LdtInformationLength, OUT PULONG ReturnLength)
NTSTATUS PspSetLdtSize (IN PEPROCESS Process, IN PPROCESS_LDT_SIZE LdtSize, IN ULONG LdtSizeLength)
NTSTATUS PspSetLdtInformation (IN PEPROCESS Process, IN PPROCESS_LDT_INFORMATION LdtInformation, IN ULONG LdtInformationLength)
NTSTATUS PspQueryDescriptorThread (PETHREAD Thread, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength)
VOID PspDeleteLdt (IN PEPROCESS Process)
NTSTATUS NtSetLdtEntries (IN ULONG Selector0, IN ULONG Entry0Low, IN ULONG Entry0Hi, IN ULONG Selector1, IN ULONG Entry1Low, IN ULONG Entry1Hi)

Variables

KMUTEX LdtMutex


Define Documentation

#define DESCRIPTOR_CONFORM   0x00001C00
 

Definition at line 46 of file i386/psldt.c.

Referenced by NtSetLdtEntries().

#define DESCRIPTOR_DPL   0x00006000
 

Definition at line 47 of file i386/psldt.c.

Referenced by NtSetLdtEntries().

#define DESCRIPTOR_GRAN   0x00800000
 

Definition at line 43 of file i386/psldt.c.

Referenced by NtSetLdtEntries().

#define DESCRIPTOR_NP   0x00008000
 

Definition at line 44 of file i386/psldt.c.

Referenced by NtSetLdtEntries().

#define DESCRIPTOR_SYSTEM   0x00001000
 

Definition at line 45 of file i386/psldt.c.

Referenced by NtSetLdtEntries().

#define DESCRIPTOR_TYPEDPL   0x00007F00
 

Definition at line 48 of file i386/psldt.c.

Referenced by NtSetLdtEntries().


Function Documentation

NTSTATUS NtSetLdtEntries IN ULONG  Selector0,
IN ULONG  Entry0Low,
IN ULONG  Entry0Hi,
IN ULONG  Selector1,
IN ULONG  Entry1Low,
IN ULONG  Entry1Hi
 

Definition at line 1235 of file i386/psldt.c.

References ASSERT, DESCRIPTOR_CONFORM, DESCRIPTOR_DPL, DESCRIPTOR_GRAN, DESCRIPTOR_NP, DESCRIPTOR_SYSTEM, DESCRIPTOR_TYPEDPL, ExAllocatePool, EXCEPTION_EXECUTE_HANDLER, Executive, ExFreePool(), FALSE, Ke386SetDescriptorProcess(), Ke386SetLdtProcess(), KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), L, _EPROCESS::LdtInformation, LdtMutex, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PAGED_CODE, PagedPool, _EPROCESS::Pcb, PsChargePoolQuota(), PsGetCurrentProcess, and Status.

01245 : 01246 01247 This routine sets up to two selectors in the current process's LDT. 01248 The LDT will be grown as necessary. A selector value of 0 indicates 01249 that the specified selector was not passed (allowing the setting of 01250 a single selector). 01251 01252 Arguments: 01253 01254 Selector0 -- Supplies the number of the first descriptor to set 01255 Entry0Low -- Supplies the low 32 bits of the descriptor 01256 Entry0Hi -- Supplies the high 32 bits of the descriptor 01257 Selector1 -- Supplies the number of the first descriptor to set 01258 Entry1Low -- Supplies the low 32 bits of the descriptor 01259 Entry1Hi -- Supplies the high 32 bits of the descriptor 01260 01261 Return Value: 01262 01263 TBS 01264 --*/ 01265 01266 { 01267 ULONG Base, Limit, LdtSize, AllocatedSize; 01268 NTSTATUS Status; 01269 PEPROCESS Process; 01270 LDT_ENTRY Descriptor; 01271 PLDT_ENTRY Ldt, OldLdt; 01272 PLDTINFORMATION ProcessLdtInformation; 01273 LONG MutexState; 01274 01275 PAGED_CODE(); 01276 01277 // 01278 // Verify the selectors. We do not allow selectors that point into 01279 // Kernel space, system selectors, or conforming code selectors 01280 // 01281 01282 // 01283 // Verify the selectors 01284 // 01285 if ((Selector0 & 0xFFFF0000) || (Selector1 & 0xFFFF0000)) { 01286 return STATUS_INVALID_LDT_DESCRIPTOR; 01287 } 01288 01289 // Change the selector values to indexes into the LDT 01290 01291 Selector0 = Selector0 & ~(RPL_MASK | SELECTOR_TABLE_INDEX); 01292 Selector1 = Selector1 & ~(RPL_MASK | SELECTOR_TABLE_INDEX); 01293 01294 01295 // 01296 // Verify descriptor 0 01297 // 01298 01299 if (Selector0) { 01300 01301 // Form the base and the limit 01302 Base = ((Entry0Low & 0xFFFF0000) >> 16) + ((Entry0Hi & 0xFF) << 16) 01303 + (Entry0Hi & 0xFF000000); 01304 01305 Limit = (Entry0Low & 0xFFFF) + (Entry0Hi & 0xF0000); 01306 01307 // N.B. the interpretation of the limit depends on the G bit 01308 // in the descriptor 01309 01310 if (Entry0Hi & DESCRIPTOR_GRAN) { 01311 Limit = (Limit << 12) | 0xFFF; 01312 } 01313 01314 // 01315 // Base and limit don't matter for NP descriptors, so only check 01316 // for present descriptors 01317 // 01318 if (Entry0Hi & DESCRIPTOR_NP) { 01319 01320 // Check descriptor base and limit 01321 if (((PVOID)Base > MM_HIGHEST_USER_ADDRESS) 01322 || ((PVOID)Base > (PVOID) (Base + Limit)) 01323 || ((PVOID)(Base + Limit) > MM_HIGHEST_USER_ADDRESS)) 01324 { 01325 return STATUS_INVALID_LDT_DESCRIPTOR; 01326 } 01327 01328 } 01329 // 01330 // If type and DPL are 0, this is an invalid descriptor, otherwise, 01331 // we have to check the type (invalid from the standpoint of a 01332 // descriptor created to generate a GP fault) 01333 // 01334 01335 if (Entry0Hi & DESCRIPTOR_TYPEDPL) { 01336 01337 // No system descriptors (system descriptors have system bit = 0) 01338 if (!(Entry0Hi & DESCRIPTOR_SYSTEM)) { 01339 return STATUS_INVALID_LDT_DESCRIPTOR; 01340 } 01341 01342 // No conforming code 01343 if ((Entry0Hi & DESCRIPTOR_CONFORM) == DESCRIPTOR_CONFORM) { 01344 return STATUS_INVALID_LDT_DESCRIPTOR; 01345 } 01346 01347 // Dpl must be 3 01348 if ((Entry0Hi & DESCRIPTOR_DPL) != DESCRIPTOR_DPL) { 01349 return STATUS_INVALID_LDT_DESCRIPTOR; 01350 } 01351 } 01352 } 01353 01354 // 01355 // Verify descriptor 1 01356 // 01357 01358 if (Selector1) { 01359 01360 // Form the base and the limit 01361 Base = ((Entry1Low & 0xFFFF0000) >> 16) + ((Entry1Hi & 0xFF) << 16) 01362 + (Entry1Hi & 0xFF000000); 01363 01364 Limit = (Entry1Low & 0xFFFF) + (Entry1Hi & 0xF0000); 01365 01366 // N.B. the interpretation of the limit depends on the G bit 01367 // in the descriptor 01368 01369 if (Entry1Hi & DESCRIPTOR_GRAN) { 01370 Limit = (Limit << 12) | 0xFFF; 01371 } 01372 01373 // 01374 // Base and limit don't matter for NP descriptor, so only check 01375 // for present descriptors 01376 // 01377 if (Entry1Hi & DESCRIPTOR_NP) { 01378 01379 // Check descriptor base and limit 01380 if (((PVOID)Base > MM_HIGHEST_USER_ADDRESS) 01381 || ((PVOID)Base > (PVOID) (Base + Limit)) 01382 || ((PVOID)(Base + Limit) > MM_HIGHEST_USER_ADDRESS)) 01383 { 01384 return STATUS_INVALID_LDT_DESCRIPTOR; 01385 } 01386 } 01387 // 01388 // If type and DPL are 0, this is an invalid descriptor, otherwise, 01389 // we have to check the type (invalid from the standpoint of a 01390 // descriptor created to generate a GP fault) 01391 // 01392 01393 if (Entry1Hi & DESCRIPTOR_TYPEDPL) { 01394 01395 // No system descriptors (system descriptors have system bit = 0) 01396 if (!(Entry1Hi & DESCRIPTOR_SYSTEM)) { 01397 return STATUS_INVALID_LDT_DESCRIPTOR; 01398 } 01399 01400 // No conforming code 01401 if ((Entry1Hi & DESCRIPTOR_CONFORM) == DESCRIPTOR_CONFORM) { 01402 return STATUS_INVALID_LDT_DESCRIPTOR; 01403 } 01404 01405 // Dpl must be 3 01406 if ((Entry1Hi & DESCRIPTOR_DPL) != DESCRIPTOR_DPL) { 01407 return STATUS_INVALID_LDT_DESCRIPTOR; 01408 } 01409 } 01410 } 01411 01412 // 01413 // Acquire the LDT mutex. 01414 // 01415 01416 Status = KeWaitForSingleObject( 01417 &LdtMutex, 01418 Executive, 01419 KernelMode, 01420 FALSE, 01421 NULL 01422 ); 01423 if ( !NT_SUCCESS(Status) ) { 01424 return Status; 01425 } 01426 01427 // 01428 // Figure out how large the LDT needs to be 01429 // 01430 01431 if (Selector0 > Selector1) { 01432 LdtSize = Selector0 + sizeof(LDT_ENTRY); 01433 } else { 01434 LdtSize = Selector1 + sizeof(LDT_ENTRY); 01435 } 01436 01437 Process = PsGetCurrentProcess(); 01438 ProcessLdtInformation = Process->LdtInformation; 01439 01440 // 01441 // Most of the time, the process will already have an LDT, and it 01442 // will be large enough. for this, we just set the descriptors and 01443 // return 01444 // 01445 01446 if (ProcessLdtInformation) { 01447 01448 // 01449 // If the LDT descriptor does not have to be modified. 01450 // 01451 if (ProcessLdtInformation->Size >= LdtSize) { 01452 if (Selector0) { 01453 01454 *((PULONG)(&Descriptor)) = Entry0Low; 01455 *(((PULONG)(&Descriptor)) + 1) = Entry0Hi; 01456 01457 Ke386SetDescriptorProcess( 01458 &(Process->Pcb), 01459 Selector0, 01460 Descriptor 01461 ); 01462 } 01463 01464 if (Selector1) { 01465 01466 *((PULONG)(&Descriptor)) = Entry1Low; 01467 *(((PULONG)(&Descriptor)) + 1) = Entry1Hi; 01468 01469 Ke386SetDescriptorProcess( 01470 &(Process->Pcb), 01471 Selector1, 01472 Descriptor 01473 ); 01474 } 01475 01476 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 01477 ASSERT(( MutexState == 0 )); 01478 return STATUS_SUCCESS; 01479 01480 // 01481 // Else if the Ldt will fit in the memory currently allocated 01482 // 01483 } else if (ProcessLdtInformation->AllocatedSize >= LdtSize) { 01484 01485 // 01486 // First remove the LDT. This will allow us to edit the memory. 01487 // We will then put the LDT back. Since we have to change the 01488 // limit anyway, it would take two calls to the kernel ldt 01489 // management minimum to set the descriptors. Each of those calls 01490 // would stall all of the processors in an MP system. If we 01491 // didn't remove the ldt first, and we were setting two descriptors, 01492 // we would have to call the LDT management 3 times (once per 01493 // descriptor, and once to change the limit of the LDT). 01494 // 01495 01496 Ke386SetLdtProcess( 01497 &(Process->Pcb), 01498 NULL, 01499 0L 01500 ); 01501 01502 // 01503 // Set the Descriptors in the LDT 01504 // 01505 if (Selector0) { 01506 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector0/sizeof(LDT_ENTRY)]))) = Entry0Low; 01507 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector0/sizeof(LDT_ENTRY)])) + 1) = 01508 Entry0Hi; 01509 } 01510 01511 if (Selector1) { 01512 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector1/sizeof(LDT_ENTRY)]))) = Entry1Low; 01513 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector1/sizeof(LDT_ENTRY)])) + 1) = 01514 Entry1Hi; 01515 } 01516 01517 // 01518 // Set the LDT for the process 01519 // 01520 01521 ProcessLdtInformation->Size = LdtSize; 01522 01523 Ke386SetLdtProcess( 01524 &(Process->Pcb), 01525 ProcessLdtInformation->Ldt, 01526 ProcessLdtInformation->Size 01527 ); 01528 01529 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 01530 ASSERT(( MutexState == 0 )); 01531 return STATUS_SUCCESS; 01532 // 01533 // Otherwise, we have to grow the LDT allocation 01534 // 01535 } 01536 } 01537 01538 // 01539 // If the process does not yet have an LDT information structure, 01540 // allocate and attach one. 01541 // 01542 01543 OldLdt = NULL; 01544 01545 if (!Process->LdtInformation) { 01546 ProcessLdtInformation = ExAllocatePool( 01547 PagedPool, 01548 sizeof(LDTINFORMATION) 01549 ); 01550 if (ProcessLdtInformation == NULL) { 01551 goto SetLdtEntriesCleanup; 01552 } 01553 Process->LdtInformation = ProcessLdtInformation; 01554 ProcessLdtInformation->Size = 0L; 01555 ProcessLdtInformation->AllocatedSize = 0L; 01556 ProcessLdtInformation->Ldt = NULL; 01557 } 01558 01559 // 01560 // Now, we either need to create or grow an LDT, so allocate some 01561 // memory, and copy as necessary 01562 // 01563 01564 AllocatedSize = (LdtSize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 01565 01566 Ldt = ExAllocatePool( 01567 PagedPool, 01568 AllocatedSize 01569 ); 01570 01571 if (Ldt) { 01572 RtlZeroMemory( 01573 Ldt, 01574 AllocatedSize 01575 ); 01576 } else { 01577 goto SetLdtEntriesCleanup; 01578 } 01579 01580 01581 if (ProcessLdtInformation->Ldt) { 01582 // 01583 // copy the contents of the old ldt 01584 // 01585 RtlMoveMemory( 01586 Ldt, 01587 ProcessLdtInformation->Ldt, 01588 ProcessLdtInformation->Size 01589 ); 01590 01591 try { 01592 PsChargePoolQuota( 01593 Process, 01594 PagedPool, 01595 AllocatedSize - ProcessLdtInformation->AllocatedSize 01596 ); 01597 } except(EXCEPTION_EXECUTE_HANDLER) { 01598 Status = GetExceptionCode(); 01599 ExFreePool(Ldt); 01600 Ldt = NULL; 01601 } 01602 01603 if (Ldt == NULL) { 01604 goto SetLdtEntriesCleanup; 01605 } 01606 01607 } else { 01608 try { 01609 PsChargePoolQuota( 01610 Process, 01611 PagedPool, 01612 AllocatedSize 01613 ); 01614 } except(EXCEPTION_EXECUTE_HANDLER) { 01615 Status = GetExceptionCode(); 01616 ExFreePool(Ldt); 01617 Ldt = NULL; 01618 } 01619 01620 if (Ldt == NULL) { 01621 goto SetLdtEntriesCleanup; 01622 } 01623 } 01624 01625 OldLdt = ProcessLdtInformation->Ldt; 01626 ProcessLdtInformation->Size = LdtSize; 01627 ProcessLdtInformation->AllocatedSize = AllocatedSize; 01628 ProcessLdtInformation->Ldt = Ldt; 01629 01630 // 01631 // Set the descriptors in the LDT 01632 // 01633 01634 if (Selector0) { 01635 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector0/sizeof(LDT_ENTRY)]))) = Entry0Low; 01636 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector0/sizeof(LDT_ENTRY)])) + 1) = 01637 Entry0Hi; 01638 } 01639 01640 if (Selector1) { 01641 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector1/sizeof(LDT_ENTRY)]))) = Entry1Low; 01642 *((PULONG)(&(ProcessLdtInformation->Ldt[Selector1/sizeof(LDT_ENTRY)])) + 1) = 01643 Entry1Hi; 01644 } 01645 01646 // 01647 // Set the LDT for the process 01648 // 01649 01650 Ke386SetLdtProcess( 01651 &(Process->Pcb), 01652 ProcessLdtInformation->Ldt, 01653 ProcessLdtInformation->Size 01654 ); 01655 01656 // 01657 // Cleanup and exit 01658 // 01659 01660 Status = STATUS_SUCCESS; 01661 01662 SetLdtEntriesCleanup: 01663 01664 if (OldLdt) { 01665 ExFreePool(OldLdt); 01666 } 01667 01668 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 01669 ASSERT(( MutexState == 0 )); 01670 return Status; 01671 01672 } }

PLDT_ENTRY PspCreateLdt IN PLDT_ENTRY  Ldt,
IN ULONG  Offset,
IN ULONG  Size,
IN ULONG  AllocationSize
 

Definition at line 902 of file i386/psldt.c.

References ASSERT, ExAllocatePool, NULL, Offset, PAGED_CODE, PagedPool, and Size.

Referenced by PspSetLdtInformation(), and PspSetLdtSize().

00911 : 00912 00913 This routine allocates space in paged pool for an LDT, and copies the 00914 specified selectors into it. IT DOES NOT VALIDATE THE SELECTORS. 00915 Selector validation must be done before calling this routine. IT 00916 DOES NOT CHARGE THE QUOTA FOR THE LDT. 00917 00918 Arguments: 00919 00920 Ldt -- Supplies a pointer to the descriptors to be put into the Ldt. 00921 Offset -- Supplies the offset in the LDT to copy the descriptors to. 00922 Size -- Supplies the actualsize of the new Ldt 00923 AllocationSize -- Supplies the size to allocate 00924 00925 Return Value: 00926 00927 Pointer to the new Ldt 00928 --*/ 00929 { 00930 PLDT_ENTRY NewLdt; 00931 00932 PAGED_CODE(); 00933 00934 ASSERT(( AllocationSize >= Size )); 00935 ASSERT(( (Size % sizeof(LDT_ENTRY)) == 0 )); 00936 00937 NewLdt = ExAllocatePool( PagedPool, AllocationSize ); 00938 if (NewLdt == NULL) { 00939 return NewLdt; 00940 } 00941 00942 00943 RtlZeroMemory( NewLdt, AllocationSize ); 00944 RtlMoveMemory( (PCHAR)NewLdt + Offset, Ldt, Size - Offset ); 00945 00946 return NewLdt; 00947 }

VOID PspDeleteLdt IN PEPROCESS  Process  ) 
 

Definition at line 1202 of file i386/psldt.c.

References ExFreePool(), NULL, and PAGED_CODE.

01207 : 01208 01209 This routine frees the paged pool associated with a process' Ldt, if 01210 it has one. 01211 01212 Arguments: 01213 01214 Process -- Supplies a pointer to the process 01215 01216 Return Value: 01217 01218 None 01219 --*/ 01220 { 01221 PLDTINFORMATION LdtInformation; 01222 01223 PAGED_CODE(); 01224 01225 LdtInformation = Process->LdtInformation; 01226 if ( LdtInformation != NULL ) { 01227 if ( LdtInformation->Ldt != NULL ) { 01228 ExFreePool( LdtInformation->Ldt ); 01229 } 01230 ExFreePool( LdtInformation ); 01231 } 01232 }

BOOLEAN PspIsDescriptorValid IN PLDT_ENTRY  Descriptor  ) 
 

Definition at line 952 of file i386/psldt.c.

References FALSE, PAGED_CODE, and TRUE.

Referenced by PspSetLdtInformation().

00958 : 00959 00960 This function determines if the supplied descriptor is valid to put 00961 into a process Ldt. For the descriptor to be valid it must have the 00962 following characteristics: 00963 00964 Base < MM_HIGHEST_USER_ADDRESS 00965 Base + Limit < MM_HIGHEST_USER_ADDRESS 00966 Type must be 00967 ReadWrite, ReadOnly, ExecuteRead, ExecuteOnly, or Invalid 00968 big or small 00969 normal or grow down 00970 Not a system descriptor (system bit is 1 == application) 00971 This rules out all gates, etc 00972 Not conforming 00973 DPL must be 3 00974 00975 Arguments: 00976 00977 Descriptor -- Supplies a pointer to the descriptor to check 00978 00979 Return Value: 00980 00981 True if the descriptor is valid (note: valid to put into an LDT. This 00982 includes Invalid descriptors) 00983 False if not 00984 --*/ 00985 00986 { 00987 ULONG Base; 00988 ULONG Limit; 00989 00990 PAGED_CODE(); 00991 00992 // 00993 // if descriptor is an invalid descriptor 00994 // 00995 00996 if ( (Descriptor->HighWord.Bits.Type == 0) && 00997 (Descriptor->HighWord.Bits.Dpl == 0) ) { 00998 00999 return TRUE; 01000 } 01001 01002 Base = Descriptor->BaseLow | (Descriptor->HighWord.Bytes.BaseMid << 16) | 01003 (Descriptor->HighWord.Bytes.BaseHi << 24); 01004 01005 Limit = Descriptor->LimitLow | (Descriptor->HighWord.Bits.LimitHi << 16); 01006 01007 // 01008 // Only have to check for present selectors 01009 // 01010 if (Descriptor->HighWord.Bits.Pres) { 01011 ULONG ActualLimit; 01012 01013 if ( (PVOID)Base > MM_HIGHEST_USER_ADDRESS ) { 01014 return FALSE; 01015 } 01016 01017 ActualLimit = (Limit << (Descriptor->HighWord.Bits.Granularity * 01018 12)) + 0xFFF * Descriptor->HighWord.Bits.Granularity; 01019 01020 if ( (Base > (Base + ActualLimit)) 01021 || ((PVOID)(Base + ActualLimit) > MM_HIGHEST_USER_ADDRESS) 01022 ) { 01023 01024 return FALSE; 01025 } 01026 01027 } 01028 01029 // 01030 // if descriptor is a system descriptor (which includes gates) 01031 // if bit 4 of the Type field is 0, then it's a system descriptor, 01032 // and we don't like it. 01033 // 01034 01035 if ( ! (Descriptor->HighWord.Bits.Type & 0x10)) { 01036 return FALSE; 01037 } 01038 01039 // 01040 // if descriptor is conforming code 01041 // 01042 01043 if ( ((Descriptor->HighWord.Bits.Type & 0x18) == 0x18) && 01044 (Descriptor->HighWord.Bits.Type & 0x4)) { 01045 01046 return FALSE; 01047 } 01048 01049 // 01050 // if Dpl is not 3 01051 // 01052 01053 if ( Descriptor->HighWord.Bits.Dpl != 3 ) { 01054 return FALSE; 01055 } 01056 01057 return TRUE; 01058 }

NTSTATUS PspLdtInitialize  ) 
 

Definition at line 84 of file i386/psldt.c.

References KeInitializeMutex(), LdtMutex, and MUTEX_LEVEL_PS_LDT.

Referenced by PspInitPhase0().

00089 : 00090 00091 This routine initializes the Ldt support for the x86 00092 00093 Arguments: 00094 00095 None 00096 00097 Return Value: 00098 00099 TBS 00100 --*/ 00101 { 00102 KeInitializeMutex( &LdtMutex, MUTEX_LEVEL_PS_LDT ); 00103 return STATUS_SUCCESS; 00104 }

NTSTATUS PspQueryDescriptorThread PETHREAD  Thread,
PVOID  ThreadInformation,
ULONG  ThreadInformationLength,
PULONG  ReturnLength
 

Definition at line 1061 of file i386/psldt.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, Executive, FALSE, Ke386GetGdtEntryThread(), KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), _EPROCESS::LdtInformation, LdtMutex, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, _ETHREAD::Tcb, THREAD_TO_PROCESS, and TRUE.

01069 : 01070 01071 This function retrieves a descriptor table entry for the specified thread. 01072 This entry may be in either the Gdt or the Ldt, as specfied by the 01073 supplied selector 01074 01075 Arguments: 01076 01077 Thread -- Supplies a pointer to the thread. 01078 ThreadInformation -- Supplies information on the descriptor. 01079 ThreadInformationLength -- Supplies the length of the information. 01080 ReturnLength -- Returns the number of bytes returned. 01081 01082 Return Value: 01083 01084 TBS 01085 --*/ 01086 { 01087 DESCRIPTOR_TABLE_ENTRY DescriptorEntry; 01088 PEPROCESS Process; 01089 BOOLEAN ReturnNow = FALSE; 01090 LONG MutexState; 01091 NTSTATUS Status; 01092 01093 PAGED_CODE(); 01094 01095 ASSERT( sizeof(KGDTENTRY) == sizeof(LDT_ENTRY) ); 01096 01097 // 01098 // Verify parameters 01099 // 01100 01101 if ( ThreadInformationLength != sizeof(DESCRIPTOR_TABLE_ENTRY) ) { 01102 return STATUS_INFO_LENGTH_MISMATCH; 01103 } 01104 01105 try { 01106 DescriptorEntry = *(PDESCRIPTOR_TABLE_ENTRY)ThreadInformation; 01107 } except(EXCEPTION_EXECUTE_HANDLER){ 01108 ReturnNow = TRUE; 01109 } 01110 01111 if (ReturnNow) { 01112 return STATUS_SUCCESS; 01113 } 01114 01115 Status = STATUS_SUCCESS; 01116 01117 // 01118 // If its a Gdt entry, let the kernel find it for us 01119 // 01120 01121 if ( !(DescriptorEntry.Selector & SELECTOR_TABLE_INDEX) ) { 01122 01123 if ( (DescriptorEntry.Selector & 0xFFFFFFF8) >= KGDT_NUMBER * 01124 sizeof(KGDTENTRY) ) { 01125 01126 return STATUS_ACCESS_VIOLATION; 01127 } 01128 01129 try { 01130 Ke386GetGdtEntryThread( &(Thread->Tcb), 01131 DescriptorEntry.Selector & 0xFFFFFFF8, 01132 (PKGDTENTRY) 01133 &(((PDESCRIPTOR_TABLE_ENTRY)ThreadInformation)->Descriptor) 01134 ); 01135 if ( ARGUMENT_PRESENT(ReturnLength) ) { 01136 *ReturnLength = sizeof(LDT_ENTRY); 01137 } 01138 } except(EXCEPTION_EXECUTE_HANDLER) { 01139 // We want to return STATUS_SUCCESS (see module notes), so 01140 // do nothing and fall out of if. 01141 } 01142 } else { 01143 01144 // 01145 // it's an Ldt entry, so copy it from the ldt 01146 // 01147 01148 Process = THREAD_TO_PROCESS(Thread); 01149 01150 // 01151 // Acquire the Ldt Mutex 01152 // 01153 01154 Status = KeWaitForSingleObject( 01155 &LdtMutex, 01156 Executive, 01157 KernelMode, 01158 FALSE, 01159 NULL 01160 ); 01161 if ( !(NT_SUCCESS(Status)) ) { 01162 return Status; 01163 } 01164 01165 if ( Process->LdtInformation == NULL ) { 01166 01167 // If there is no Ldt 01168 Status = STATUS_NO_LDT; 01169 01170 } else if ( (DescriptorEntry.Selector & 0xFFFFFFF8) >= 01171 ((PLDTINFORMATION)(Process->LdtInformation))->Size ) { 01172 01173 // Else If the selector is outside the table 01174 Status = STATUS_ACCESS_VIOLATION; 01175 01176 } else try { 01177 01178 // Else return the contents of the descriptor 01179 RtlMoveMemory( 01180 &(((PDESCRIPTOR_TABLE_ENTRY)ThreadInformation)->Descriptor), 01181 (PCHAR)(((PLDTINFORMATION)(Process->LdtInformation))->Ldt) + 01182 (DescriptorEntry.Selector & 0xFFFFFFF8), 01183 sizeof(LDT_ENTRY) 01184 ); 01185 if (ARGUMENT_PRESENT(ReturnLength)) { 01186 *ReturnLength = sizeof(LDT_ENTRY); 01187 } 01188 01189 } except(EXCEPTION_EXECUTE_HANDLER) { 01190 // We want to return STATUS_SUCCESS (see module notes), so 01191 // do nothing and fall out of if. 01192 } 01193 01194 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 01195 ASSERT(( MutexState == 0 )); 01196 } 01197 01198 return Status; 01199 }

NTSTATUS PspQueryLdtInformation IN PEPROCESS  Process,
OUT PPROCESS_LDT_INFORMATION  LdtInformation,
IN ULONG  LdtInformationLength,
OUT PULONG  ReturnLength
 

Definition at line 108 of file i386/psldt.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, Executive, FALSE, KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), LdtMutex, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Start, Status, and TRUE.

00116 : 00117 00118 This function performs the work for the Ldt portion of the query 00119 process information function. It copies the contents of the Ldt 00120 for the specified process into the users buffer, up to the length 00121 of the buffer. 00122 00123 Arguments: 00124 00125 Process -- Supplies a pointer to the process to return LDT info for 00126 LdtInformation -- Supplies a pointer to the buffer 00127 ReturnLength -- Returns the number of bytes put into the buffer 00128 00129 Return Value: 00130 00131 TBS 00132 --*/ 00133 { 00134 ULONG CopyLength, CopyEnd; 00135 NTSTATUS Status; 00136 ULONG HeaderLength; 00137 ULONG Length, Start; 00138 LONG MutexStatus; 00139 PLDTINFORMATION ProcessLdtInfo; 00140 BOOLEAN ReturnNow = FALSE; 00141 00142 PAGED_CODE(); 00143 00144 // 00145 // Verify the parameters 00146 // 00147 00148 if ( LdtInformationLength < (ULONG)sizeof(PROCESS_LDT_INFORMATION) ) { 00149 return STATUS_INFO_LENGTH_MISMATCH; 00150 } 00151 00152 // 00153 // This portion of the parameters may be in user space 00154 // 00155 try { 00156 // 00157 // Capture parameters 00158 // 00159 Length = LdtInformation->Length; 00160 Start = LdtInformation->Start; 00161 00162 } except(EXCEPTION_EXECUTE_HANDLER) { 00163 ReturnNow = TRUE; 00164 } 00165 00166 if (ReturnNow) { 00167 return STATUS_SUCCESS; 00168 } 00169 00170 // 00171 // The buffer containing the Ldt entries must be in the information 00172 // structure. We subtract one Ldt entry, because the structure is 00173 // declared to contain one. 00174 // 00175 if (LdtInformationLength - sizeof(PROCESS_LDT_INFORMATION) + sizeof(LDT_ENTRY) < Length) { 00176 00177 return STATUS_INFO_LENGTH_MISMATCH; 00178 } 00179 00180 // An Ldt entry is a processor structure, and must be 8 bytes long 00181 ASSERT((sizeof(LDT_ENTRY) == 8)); 00182 00183 // 00184 // The length of the structure must be an even number of Ldt entries 00185 // 00186 if (Length % sizeof(LDT_ENTRY)) { 00187 return STATUS_INVALID_LDT_SIZE; 00188 } 00189 00190 // 00191 // The information to get from the Ldt must start on an Ldt entry 00192 // boundary. 00193 // 00194 if (Start % sizeof(LDT_ENTRY)) { 00195 return STATUS_INVALID_LDT_OFFSET; 00196 } 00197 00198 // 00199 // Acquire the Ldt mutex 00200 // 00201 00202 Status = KeWaitForSingleObject( 00203 &LdtMutex, 00204 Executive, 00205 KernelMode, 00206 FALSE, 00207 NULL 00208 ); 00209 if ( !NT_SUCCESS(Status) ) { 00210 return Status; 00211 } 00212 00213 ProcessLdtInfo = Process->LdtInformation; 00214 00215 // 00216 // If the process has an Ldt 00217 // 00218 if (( ProcessLdtInfo) && (ProcessLdtInfo->Size )) { 00219 00220 ASSERT ((ProcessLdtInfo->Ldt)); 00221 00222 // 00223 // Set the end of the copy to be the smaller of: 00224 // the end of the information the user requested or 00225 // the end of the information that is actually there 00226 // 00227 00228 if (ProcessLdtInfo->Size < Start) { 00229 CopyEnd = Start; 00230 } else if (ProcessLdtInfo->Size - Start > Length) { 00231 CopyEnd = Length + Start; 00232 } else { 00233 CopyEnd = ProcessLdtInfo->Size; 00234 } 00235 00236 CopyLength = CopyEnd - Start; 00237 00238 try { 00239 00240 // 00241 // Set the length field to the actual length of the Ldt 00242 // 00243 LdtInformation->Length = ProcessLdtInfo->Size; 00244 00245 // 00246 // Copy the contents of the Ldt into the user's buffer 00247 // 00248 00249 if (CopyLength) { 00250 RtlMoveMemory( 00251 &(LdtInformation->LdtEntries), 00252 (PCHAR)ProcessLdtInfo->Ldt + Start, 00253 CopyLength 00254 ); 00255 } 00256 00257 } except(EXCEPTION_EXECUTE_HANDLER) { 00258 ReturnNow = TRUE; 00259 MutexStatus = KeReleaseMutex( &LdtMutex, FALSE ); 00260 ASSERT(( MutexStatus == 0 )); 00261 } 00262 00263 00264 if (ReturnNow) { 00265 return STATUS_SUCCESS; 00266 } 00267 00268 } else { 00269 00270 // 00271 // There is no Ldt 00272 // 00273 00274 CopyLength = 0; 00275 try { 00276 LdtInformation->Length = 0; 00277 } except(EXCEPTION_EXECUTE_HANDLER) { 00278 ReturnNow = TRUE; 00279 MutexStatus = KeReleaseMutex( &LdtMutex, FALSE ); 00280 ASSERT(( MutexStatus == 0 )); 00281 } 00282 00283 if (ReturnNow) { 00284 return STATUS_SUCCESS; 00285 } 00286 } 00287 00288 // 00289 // Set the length of the information returned 00290 // 00291 if ( ARGUMENT_PRESENT(ReturnLength) ) { 00292 try { 00293 HeaderLength = (PCHAR)(&(LdtInformation->LdtEntries)) - 00294 (PCHAR)(&(LdtInformation->Start)); 00295 *ReturnLength = CopyLength + HeaderLength; 00296 } except(EXCEPTION_EXECUTE_HANDLER){ 00297 // We don't do anything here because we want to return success 00298 } 00299 } 00300 00301 MutexStatus = KeReleaseMutex( &LdtMutex, FALSE ); 00302 ASSERT(( MutexStatus == 0 )); 00303 return STATUS_SUCCESS; 00304 }

NTSTATUS PspSetLdtInformation IN PEPROCESS  Process,
IN PPROCESS_LDT_INFORMATION  LdtInformation,
IN ULONG  LdtInformationLength
 

Definition at line 503 of file i386/psldt.c.

References ASSERT, ExAllocatePool, EXCEPTION_EXECUTE_HANDLER, Executive, ExFreePool(), FALSE, Ke386SetDescriptorProcess(), Ke386SetLdtProcess(), KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), LdtMutex, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PAGED_CODE, PagedPool, PsChargePoolQuota(), PspCreateLdt(), PspIsDescriptorValid(), PsReturnPoolQuota(), Size, and Status.

00511 : 00512 00513 This function alters the ldt for a specified process. It can alter 00514 portions of the LDT, or the whole LDT. If an Ldt is created or 00515 grown, the specified process will be charged the quota for the LDT. 00516 Each descriptor that is set will be verified. 00517 00518 Arguments: 00519 00520 Process -- Supplies a pointer to the process whose Ldt is to be modified 00521 LdtInformation -- Supplies a pointer to the information about the Ldt 00522 modifications 00523 LdtInformationLength -- Supplies the length of the LdtInformation 00524 structure. 00525 Return Value: 00526 00527 TBS 00528 --*/ 00529 { 00530 NTSTATUS Status; 00531 PLDT_ENTRY OldLdt = NULL; 00532 ULONG OldSize = 0; 00533 ULONG AllocatedSize; 00534 ULONG Size; 00535 ULONG MutexState; 00536 ULONG LdtOffset; 00537 PLDT_ENTRY CurrentDescriptor; 00538 PPROCESS_LDT_INFORMATION LdtInfo; 00539 PLDTINFORMATION ProcessLdtInfo; 00540 PLDT_ENTRY Ldt; 00541 00542 PAGED_CODE(); 00543 00544 if ( LdtInformationLength < (ULONG)sizeof( PROCESS_LDT_INFORMATION)) { 00545 return STATUS_INFO_LENGTH_MISMATCH; 00546 } 00547 00548 Status = STATUS_SUCCESS; 00549 // 00550 // alocate a local buffer to capture the ldt information to 00551 // 00552 try { 00553 LdtInfo = ExAllocatePool( 00554 PagedPool, 00555 LdtInformationLength 00556 ); 00557 if (LdtInfo) { 00558 // 00559 // Copy the information the user is supplying 00560 // 00561 RtlMoveMemory( 00562 LdtInfo, 00563 LdtInformation, 00564 LdtInformationLength 00565 ); 00566 } 00567 } except(EXCEPTION_EXECUTE_HANDLER) { 00568 if (LdtInfo) { 00569 ExFreePool(LdtInfo); 00570 } 00571 Status = GetExceptionCode(); 00572 } 00573 00574 // 00575 // If the capture didn't succeed 00576 // 00577 if (!NT_SUCCESS(Status)) { 00578 if (Status == STATUS_ACCESS_VIOLATION) { 00579 return STATUS_SUCCESS; 00580 } else { 00581 return Status; 00582 } 00583 } 00584 00585 if (LdtInfo == NULL) { 00586 return STATUS_INSUFFICIENT_RESOURCES; 00587 } 00588 00589 // 00590 // Verify that the Start and Length are plausible 00591 // 00592 if (LdtInfo->Start & 0xFFFF0000) { 00593 return STATUS_INVALID_LDT_OFFSET; 00594 } 00595 00596 if (LdtInfo->Length & 0xFFFF0000) { 00597 return STATUS_INVALID_LDT_SIZE; 00598 } 00599 00600 // 00601 // Insure that the buffer it large enough to contain the specified number 00602 // of selectors. 00603 // 00604 if (LdtInformationLength - sizeof(PROCESS_LDT_INFORMATION) + sizeof(LDT_ENTRY) < LdtInfo->Length) { 00605 ExFreePool(LdtInfo); 00606 return STATUS_INFO_LENGTH_MISMATCH; 00607 } 00608 00609 // 00610 // The info to set must be an integral number of selectors 00611 // 00612 if (LdtInfo->Length % sizeof(LDT_ENTRY)) { 00613 ExFreePool(LdtInfo); 00614 return STATUS_INVALID_LDT_SIZE; 00615 } 00616 00617 // 00618 // The beginning of the info must be on a selector boundary 00619 // 00620 if (LdtInfo->Start % sizeof(LDT_ENTRY)) { 00621 ExFreePool(LdtInfo); 00622 return STATUS_INVALID_LDT_OFFSET; 00623 } 00624 00625 // 00626 // Verify all of the descriptors. 00627 // 00628 00629 for (CurrentDescriptor = LdtInfo->LdtEntries; 00630 00631 (PCHAR)CurrentDescriptor < (PCHAR)LdtInfo->LdtEntries + 00632 LdtInfo->Length; 00633 00634 CurrentDescriptor++ 00635 ) { 00636 if (!PspIsDescriptorValid( CurrentDescriptor )) { 00637 ExFreePool(LdtInfo); 00638 return STATUS_INVALID_LDT_DESCRIPTOR; 00639 } 00640 } 00641 00642 // 00643 // Acquire the Ldt Mutex 00644 // 00645 00646 Status = KeWaitForSingleObject( 00647 &LdtMutex, 00648 Executive, 00649 KernelMode, 00650 FALSE, 00651 NULL 00652 ); 00653 if ( !(NT_SUCCESS(Status)) ) { 00654 return Status; 00655 } 00656 00657 ProcessLdtInfo = Process->LdtInformation; 00658 00659 // 00660 // If the process doen't have an Ldt information structure, allocate 00661 // one and attach it to the process 00662 // 00663 if ( ProcessLdtInfo == NULL ) { 00664 ProcessLdtInfo = ExAllocatePool( 00665 PagedPool, 00666 sizeof(LDTINFORMATION) 00667 ); 00668 if ( ProcessLdtInfo == NULL ) { 00669 goto SetInfoCleanup; 00670 } 00671 Process->LdtInformation = ProcessLdtInfo; 00672 RtlZeroMemory( ProcessLdtInfo, sizeof(LDTINFORMATION) ); 00673 } 00674 00675 // 00676 // If we are supposed to remove the LDT 00677 // 00678 if ( LdtInfo->Length == 0 ) { 00679 00680 // 00681 // Remove the process' Ldt 00682 // 00683 00684 if ( ProcessLdtInfo->Ldt ) { 00685 OldSize = ProcessLdtInfo->AllocatedSize; 00686 OldLdt = ProcessLdtInfo->Ldt; 00687 00688 ProcessLdtInfo->AllocatedSize = 0; 00689 ProcessLdtInfo->Size = 0; 00690 ProcessLdtInfo->Ldt = NULL; 00691 00692 Ke386SetLdtProcess( 00693 &(Process->Pcb), 00694 NULL, 00695 0 00696 ); 00697 00698 PsReturnPoolQuota( Process, PagedPool, OldSize ); 00699 } 00700 00701 00702 } else if ( ProcessLdtInfo->Ldt == NULL ) { 00703 00704 // 00705 // Create a new Ldt for the process 00706 // 00707 00708 // 00709 // Allocate an integral number of pages for the LDT. 00710 // 00711 00712 ASSERT(((PAGE_SIZE % 2) == 0)); 00713 00714 AllocatedSize = (LdtInfo->Start + LdtInfo->Length + PAGE_SIZE - 1) & 00715 ~(PAGE_SIZE - 1); 00716 00717 Size = LdtInfo->Start + LdtInfo->Length; 00718 00719 Ldt = PspCreateLdt( 00720 LdtInfo->LdtEntries, 00721 LdtInfo->Start, 00722 Size, 00723 AllocatedSize 00724 ); 00725 00726 if ( Ldt == NULL ) { 00727 Status = STATUS_INSUFFICIENT_RESOURCES; 00728 goto SetInfoCleanup; 00729 } 00730 00731 try { 00732 PsChargePoolQuota( 00733 Process, 00734 PagedPool, 00735 AllocatedSize 00736 ); 00737 } except(EXCEPTION_EXECUTE_HANDLER) { 00738 Status = GetExceptionCode(); 00739 } 00740 00741 if (!NT_SUCCESS(Status)) { 00742 goto SetInfoCleanup; 00743 } 00744 00745 ProcessLdtInfo->Ldt = Ldt; 00746 ProcessLdtInfo->Size = Size; 00747 ProcessLdtInfo->AllocatedSize = AllocatedSize; 00748 Ke386SetLdtProcess( 00749 &(Process->Pcb), 00750 ProcessLdtInfo->Ldt, 00751 ProcessLdtInfo->Size 00752 ); 00753 00754 00755 } else if ( (LdtInfo->Length + LdtInfo->Start) > ProcessLdtInfo->Size ) { 00756 00757 // 00758 // Grow the process' Ldt 00759 // 00760 00761 if ( (LdtInfo->Length + LdtInfo->Start) > 00762 ProcessLdtInfo->AllocatedSize 00763 ) { 00764 00765 // 00766 // Current Ldt allocation is not large enough, so create a 00767 // new larger Ldt 00768 // 00769 00770 OldSize = ProcessLdtInfo->AllocatedSize; 00771 00772 Size = LdtInfo->Start + LdtInfo->Length; 00773 AllocatedSize = (Size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 00774 00775 Ldt = PspCreateLdt( 00776 ProcessLdtInfo->Ldt, 00777 0, 00778 OldSize, 00779 AllocatedSize 00780 ); 00781 00782 if ( Ldt == NULL ) { 00783 Status = STATUS_INSUFFICIENT_RESOURCES; 00784 goto SetInfoCleanup; 00785 } 00786 00787 try { 00788 00789 PsChargePoolQuota( 00790 Process, 00791 PagedPool, 00792 ProcessLdtInfo->AllocatedSize - OldSize 00793 ); 00794 00795 } except(EXCEPTION_EXECUTE_HANDLER) { 00796 Status = GetExceptionCode(); 00797 } 00798 00799 if (!NT_SUCCESS(Status)) { 00800 goto SetInfoCleanup; 00801 } 00802 00803 // 00804 // Swap Ldt information 00805 // 00806 OldLdt = ProcessLdtInfo->Ldt; 00807 ProcessLdtInfo->Ldt = Ldt; 00808 ProcessLdtInfo->Size = Size; 00809 ProcessLdtInfo->AllocatedSize = AllocatedSize; 00810 00811 // 00812 // Put new selectors into the new ldt 00813 // 00814 RtlMoveMemory( 00815 (PCHAR)(ProcessLdtInfo->Ldt) + LdtInfo->Start, 00816 LdtInfo->LdtEntries, 00817 LdtInfo->Length 00818 ); 00819 00820 Ke386SetLdtProcess( 00821 &(Process->Pcb), 00822 ProcessLdtInfo->Ldt, 00823 ProcessLdtInfo->Size 00824 ); 00825 00826 00827 } else { 00828 00829 // 00830 // Current Ldt allocation is large enough 00831 // 00832 00833 ProcessLdtInfo->Size = LdtInfo->Length + LdtInfo->Start; 00834 00835 Ke386SetLdtProcess( 00836 &(Process->Pcb), 00837 ProcessLdtInfo->Ldt, 00838 ProcessLdtInfo->Size 00839 ); 00840 00841 // 00842 // Change the selectors in the table 00843 // 00844 for (LdtOffset = LdtInfo->Start, 00845 CurrentDescriptor = LdtInfo->LdtEntries; 00846 00847 LdtOffset < LdtInfo->Start + LdtInfo->Length; 00848 00849 LdtOffset += sizeof(LDT_ENTRY), 00850 CurrentDescriptor++ 00851 ) { 00852 00853 Ke386SetDescriptorProcess( 00854 &(Process->Pcb), 00855 LdtOffset, 00856 *CurrentDescriptor 00857 ); 00858 } 00859 } 00860 } else { 00861 00862 // 00863 // Simply changing some selectors 00864 // 00865 00866 for (LdtOffset = LdtInfo->Start, 00867 CurrentDescriptor = LdtInfo->LdtEntries; 00868 00869 LdtOffset < LdtInfo->Start + LdtInfo->Length; 00870 00871 LdtOffset += sizeof(LDT_ENTRY), 00872 CurrentDescriptor++ 00873 ) { 00874 00875 Ke386SetDescriptorProcess( 00876 &(Process->Pcb), 00877 LdtOffset, 00878 *CurrentDescriptor 00879 ); 00880 } 00881 Status = STATUS_SUCCESS; 00882 } 00883 00884 00885 SetInfoCleanup: 00886 00887 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 00888 ASSERT(( MutexState == 0 )); 00889 00890 if (OldLdt != NULL) { 00891 ExFreePool(OldLdt); 00892 } 00893 00894 if (LdtInfo != NULL) { 00895 ExFreePool(LdtInfo); 00896 } 00897 00898 return Status; 00899 }

NTSTATUS PspSetLdtSize IN PEPROCESS  Process,
IN PPROCESS_LDT_SIZE  LdtSize,
IN ULONG  LdtSizeLength
 

Definition at line 308 of file i386/psldt.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, Executive, ExFreePool(), FALSE, Ke386SetLdtProcess(), KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), LdtMutex, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PAGED_CODE, PagedPool, PspCreateLdt(), PsReturnPoolQuota(), Status, and TRUE.

00316 : 00317 00318 This routine changes the LDT size. It will shrink the LDT, but not 00319 grow it. If the LDT shrinks by 1 or more pages from its current allocation, 00320 the LDT will be reallocated for the new smaller size. If the allocated 00321 size of the LDT changes, the quota charge for the Ldt will be reduced. 00322 00323 Arguments: 00324 00325 Process -- Supplies a pointer to the process whose Ldt is to be sized 00326 LdtSize -- Supplies a pointer to the size information 00327 00328 Return Value: 00329 00330 TBS 00331 --*/ 00332 { 00333 ULONG OldSize = 0; 00334 LONG MutexState; 00335 ULONG Length; 00336 PLDT_ENTRY OldLdt = NULL; 00337 NTSTATUS Status; 00338 PLDTINFORMATION ProcessLdtInfo; 00339 BOOLEAN ReturnNow = FALSE; 00340 PLDT_ENTRY Ldt; 00341 00342 PAGED_CODE(); 00343 00344 // 00345 // Verify the parameters 00346 // 00347 if ( LdtSizeLength != (ULONG)sizeof( PROCESS_LDT_SIZE ) ){ 00348 return STATUS_INFO_LENGTH_MISMATCH; 00349 } 00350 00351 // 00352 // The following parameters may be in user space 00353 // 00354 try { 00355 // 00356 // Capture the new Ldt length 00357 // 00358 Length = LdtSize->Length; 00359 00360 } except(EXCEPTION_EXECUTE_HANDLER){ 00361 ReturnNow = TRUE; 00362 } 00363 00364 if (ReturnNow) { 00365 return STATUS_SUCCESS; 00366 } 00367 00368 ASSERT((sizeof(LDT_ENTRY) == 8)); 00369 00370 // 00371 // The Ldt must always be an integral number of LDT_ENTRIES 00372 // 00373 if (Length % sizeof(LDT_ENTRY)) { 00374 return STATUS_INVALID_LDT_SIZE; 00375 } 00376 00377 // 00378 // Acquire the Ldt Mutex 00379 // 00380 00381 Status = KeWaitForSingleObject( 00382 &LdtMutex, 00383 Executive, 00384 KernelMode, 00385 FALSE, 00386 NULL 00387 ); 00388 if ( !(NT_SUCCESS(Status)) ) { 00389 return Status; 00390 } 00391 00392 // 00393 // If there isn't an Ldt we can't set the size of the LDT 00394 // 00395 ProcessLdtInfo = Process->LdtInformation; 00396 if ((ProcessLdtInfo == NULL) || (ProcessLdtInfo->Size == 0)) { 00397 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 00398 ASSERT((MutexState == 0)); 00399 return STATUS_NO_LDT; 00400 } 00401 00402 // 00403 // This function cannot be used to grow the Ldt 00404 // 00405 if (Length > ProcessLdtInfo->Size) { 00406 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 00407 ASSERT((MutexState == 0)); 00408 return STATUS_INVALID_LDT_SIZE; 00409 } 00410 00411 // 00412 // Later, we will set ProcessLdtInfo->Ldt = Ldt. We may set the value 00413 // of Ldt in the if statement below, but there is one case where we 00414 // don't 00415 // 00416 Ldt = ProcessLdtInfo->Ldt; 00417 00418 // 00419 // Adjust the size of the LDT 00420 // 00421 00422 ProcessLdtInfo->Size = Length; 00423 00424 // 00425 // Free some of the Ldt memory if conditions allow 00426 // 00427 00428 if ( Length == 0 ) { 00429 00430 OldSize = ProcessLdtInfo->AllocatedSize; 00431 OldLdt = ProcessLdtInfo->Ldt; 00432 00433 ProcessLdtInfo->AllocatedSize = 0; 00434 Ldt = NULL; 00435 00436 } else if ( (ProcessLdtInfo->AllocatedSize - ProcessLdtInfo->Size) >= 00437 PAGE_SIZE 00438 ) { 00439 00440 OldSize = ProcessLdtInfo->AllocatedSize; 00441 OldLdt = ProcessLdtInfo->Ldt; 00442 00443 // 00444 // Calculate new Ldt size (lowest integer number of pages 00445 // large enough) 00446 // 00447 00448 ProcessLdtInfo->AllocatedSize = (ProcessLdtInfo->Size + PAGE_SIZE - 1) 00449 & ~(PAGE_SIZE - 1); 00450 00451 // 00452 // Reallocate and copy the Ldt 00453 // 00454 Ldt = PspCreateLdt( 00455 ProcessLdtInfo->Ldt, 00456 0, 00457 ProcessLdtInfo->Size, 00458 ProcessLdtInfo->AllocatedSize 00459 ); 00460 00461 if ( Ldt == NULL ) { 00462 // We cannot reduce the allocation, but we can reduce the 00463 // Ldt selector limit (done using Ke386SetLdtProcess) 00464 Ldt = OldLdt; 00465 ProcessLdtInfo->AllocatedSize = OldSize; 00466 OldLdt = NULL; 00467 } 00468 } 00469 00470 ProcessLdtInfo->Ldt = Ldt; 00471 00472 // 00473 // Change the limit on the Process Ldt 00474 // 00475 00476 Ke386SetLdtProcess( 00477 &(Process->Pcb), 00478 ProcessLdtInfo->Ldt, 00479 ProcessLdtInfo->Size 00480 ); 00481 00482 // 00483 // If we resized the Ldt, free to old one and reduce the quota charge 00484 // 00485 00486 if (OldLdt) { 00487 ExFreePool( OldLdt ); 00488 00489 PsReturnPoolQuota( 00490 Process, 00491 PagedPool, 00492 OldSize - ProcessLdtInfo->AllocatedSize 00493 ); 00494 } 00495 00496 MutexState = KeReleaseMutex( &LdtMutex, FALSE ); 00497 ASSERT((MutexState == 0)); 00498 return STATUS_SUCCESS; 00499 }


Variable Documentation

KMUTEX LdtMutex
 

Definition at line 51 of file i386/psldt.c.

Referenced by NtSetLdtEntries(), PspLdtInitialize(), PspQueryDescriptorThread(), PspQueryLdtInformation(), PspSetLdtInformation(), and PspSetLdtSize().


Generated on Sat May 15 19:45:23 2004 for test by doxygen 1.3.7