00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
#include "psp.h"
00038
00039
00040
00041
00042
00043 #define DESCRIPTOR_GRAN 0x00800000
00044 #define DESCRIPTOR_NP 0x00008000
00045 #define DESCRIPTOR_SYSTEM 0x00001000
00046 #define DESCRIPTOR_CONFORM 0x00001C00
00047 #define DESCRIPTOR_DPL 0x00006000
00048 #define DESCRIPTOR_TYPEDPL 0x00007F00
00049
00050
00051 KMUTEX LdtMutex;
00052
00053
00054
00055
00056
00057 PLDT_ENTRY
00058
PspCreateLdt(
00059 IN PLDT_ENTRY Ldt,
00060 IN ULONG Offset,
00061 IN ULONG Size,
00062 IN ULONG AllocationSize
00063 );
00064
00065 BOOLEAN
00066
PspIsDescriptorValid(
00067 IN PLDT_ENTRY Descriptor
00068 );
00069
00070
#ifdef ALLOC_PRAGMA
00071
#pragma alloc_text(INIT, PspLdtInitialize)
00072
#pragma alloc_text(PAGE, NtSetLdtEntries)
00073
#pragma alloc_text(PAGE, PspDeleteLdt)
00074
#pragma alloc_text(PAGE, PspQueryLdtInformation)
00075
#pragma alloc_text(PAGE, PspSetLdtSize)
00076
#pragma alloc_text(PAGE, PspSetLdtInformation)
00077
#pragma alloc_text(PAGE, PspCreateLdt)
00078
#pragma alloc_text(PAGE, PspIsDescriptorValid)
00079
#pragma alloc_text(PAGE, PspQueryDescriptorThread)
00080
#endif
00081
00082
00083
NTSTATUS
00084 PspLdtInitialize(
00085 )
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 {
00102
KeInitializeMutex( &
LdtMutex,
MUTEX_LEVEL_PS_LDT );
00103
return STATUS_SUCCESS;
00104 }
00105
00106
00107
NTSTATUS
00108 PspQueryLdtInformation(
00109 IN
PEPROCESS Process,
00110 OUT PPROCESS_LDT_INFORMATION LdtInformation,
00111 IN ULONG LdtInformationLength,
00112 OUT PULONG ReturnLength
00113 )
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
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
00146
00147
00148
if ( LdtInformationLength < (ULONG)
sizeof(PROCESS_LDT_INFORMATION) ) {
00149
return STATUS_INFO_LENGTH_MISMATCH;
00150 }
00151
00152
00153
00154
00155
try {
00156
00157
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
00172
00173
00174
00175
if (LdtInformationLength -
sizeof(PROCESS_LDT_INFORMATION) +
sizeof(LDT_ENTRY) < Length) {
00176
00177
return STATUS_INFO_LENGTH_MISMATCH;
00178 }
00179
00180
00181
ASSERT((
sizeof(LDT_ENTRY) == 8));
00182
00183
00184
00185
00186
if (Length %
sizeof(LDT_ENTRY)) {
00187
return STATUS_INVALID_LDT_SIZE;
00188 }
00189
00190
00191
00192
00193
00194
if (
Start %
sizeof(LDT_ENTRY)) {
00195
return STATUS_INVALID_LDT_OFFSET;
00196 }
00197
00198
00199
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
00217
00218
if (( ProcessLdtInfo) && (ProcessLdtInfo->Size )) {
00219
00220
ASSERT ((ProcessLdtInfo->Ldt));
00221
00222
00223
00224
00225
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
00242
00243 LdtInformation->Length = ProcessLdtInfo->Size;
00244
00245
00246
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
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
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
00298 }
00299 }
00300
00301 MutexStatus =
KeReleaseMutex( &
LdtMutex,
FALSE );
00302
ASSERT(( MutexStatus == 0 ));
00303
return STATUS_SUCCESS;
00304 }
00305
00306
00307
NTSTATUS
00308 PspSetLdtSize(
00309 IN
PEPROCESS Process,
00310 IN PPROCESS_LDT_SIZE LdtSize,
00311 IN ULONG LdtSizeLength
00312 )
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
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
00346
00347
if ( LdtSizeLength != (ULONG)
sizeof( PROCESS_LDT_SIZE ) ){
00348
return STATUS_INFO_LENGTH_MISMATCH;
00349 }
00350
00351
00352
00353
00354
try {
00355
00356
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
00372
00373
if (Length %
sizeof(LDT_ENTRY)) {
00374
return STATUS_INVALID_LDT_SIZE;
00375 }
00376
00377
00378
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
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
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
00413
00414
00415
00416 Ldt = ProcessLdtInfo->Ldt;
00417
00418
00419
00420
00421
00422 ProcessLdtInfo->Size = Length;
00423
00424
00425
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
00445
00446
00447
00448 ProcessLdtInfo->AllocatedSize = (ProcessLdtInfo->Size +
PAGE_SIZE - 1)
00449 & ~(
PAGE_SIZE - 1);
00450
00451
00452
00453
00454 Ldt =
PspCreateLdt(
00455 ProcessLdtInfo->Ldt,
00456 0,
00457 ProcessLdtInfo->Size,
00458 ProcessLdtInfo->AllocatedSize
00459 );
00460
00461
if ( Ldt ==
NULL ) {
00462
00463
00464 Ldt = OldLdt;
00465 ProcessLdtInfo->AllocatedSize = OldSize;
00466 OldLdt =
NULL;
00467 }
00468 }
00469
00470 ProcessLdtInfo->Ldt = Ldt;
00471
00472
00473
00474
00475
00476
Ke386SetLdtProcess(
00477 &(Process->Pcb),
00478 ProcessLdtInfo->Ldt,
00479 ProcessLdtInfo->Size
00480 );
00481
00482
00483
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 }
00500
00501
00502
NTSTATUS
00503 PspSetLdtInformation(
00504 IN
PEPROCESS Process,
00505 IN PPROCESS_LDT_INFORMATION LdtInformation,
00506 IN ULONG LdtInformationLength
00507 )
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
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
00551
00552
try {
00553 LdtInfo =
ExAllocatePool(
00554
PagedPool,
00555 LdtInformationLength
00556 );
00557
if (LdtInfo) {
00558
00559
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
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
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
00602
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
00611
00612
if (LdtInfo->Length %
sizeof(LDT_ENTRY)) {
00613
ExFreePool(LdtInfo);
00614
return STATUS_INVALID_LDT_SIZE;
00615 }
00616
00617
00618
00619
00620
if (LdtInfo->Start %
sizeof(LDT_ENTRY)) {
00621
ExFreePool(LdtInfo);
00622
return STATUS_INVALID_LDT_OFFSET;
00623 }
00624
00625
00626
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
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
00661
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
00677
00678
if ( LdtInfo->Length == 0 ) {
00679
00680
00681
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
00706
00707
00708
00709
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
00759
00760
00761
if ( (LdtInfo->Length + LdtInfo->Start) >
00762 ProcessLdtInfo->AllocatedSize
00763 ) {
00764
00765
00766
00767
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
00805
00806 OldLdt = ProcessLdtInfo->Ldt;
00807 ProcessLdtInfo->Ldt = Ldt;
00808 ProcessLdtInfo->Size =
Size;
00809 ProcessLdtInfo->AllocatedSize = AllocatedSize;
00810
00811
00812
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
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
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
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 }
00900
00901 PLDT_ENTRY
00902 PspCreateLdt(
00903 IN PLDT_ENTRY Ldt,
00904 IN ULONG Offset,
00905 IN ULONG Size,
00906 IN ULONG AllocationSize
00907 )
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
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 }
00948
00949
00950
00951 BOOLEAN
00952 PspIsDescriptorValid(
00953 IN PLDT_ENTRY Descriptor
00954 )
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 {
00987 ULONG Base;
00988 ULONG Limit;
00989
00990
PAGED_CODE();
00991
00992
00993
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
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
01031
01032
01033
01034
01035
if ( ! (Descriptor->HighWord.Bits.Type & 0x10)) {
01036
return FALSE;
01037 }
01038
01039
01040
01041
01042
01043
if ( ((Descriptor->HighWord.Bits.Type & 0x18) == 0x18) &&
01044 (Descriptor->HighWord.Bits.Type & 0x4)) {
01045
01046
return FALSE;
01047 }
01048
01049
01050
01051
01052
01053
if ( Descriptor->HighWord.Bits.Dpl != 3 ) {
01054
return FALSE;
01055 }
01056
01057
return TRUE;
01058 }
01059
01060
NTSTATUS
01061 PspQueryDescriptorThread (
01062
PETHREAD Thread,
01063 PVOID ThreadInformation,
01064 ULONG ThreadInformationLength,
01065 PULONG ReturnLength
01066 )
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
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
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
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
01140
01141 }
01142 }
else {
01143
01144
01145
01146
01147
01148 Process =
THREAD_TO_PROCESS(Thread);
01149
01150
01151
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
01168
Status = STATUS_NO_LDT;
01169
01170 }
else if ( (DescriptorEntry.Selector & 0xFFFFFFF8) >=
01171 ((PLDTINFORMATION)(Process->
LdtInformation))->Size ) {
01172
01173
01174
Status = STATUS_ACCESS_VIOLATION;
01175
01176 }
else try {
01177
01178
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
01191
01192 }
01193
01194 MutexState =
KeReleaseMutex( &
LdtMutex,
FALSE );
01195
ASSERT(( MutexState == 0 ));
01196 }
01197
01198
return Status;
01199 }
01200
01201
VOID
01202 PspDeleteLdt(
01203 IN
PEPROCESS Process
01204 )
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
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 }
01233
01234
NTSTATUS
01235 NtSetLdtEntries(
01236 IN ULONG Selector0,
01237 IN ULONG Entry0Low,
01238 IN ULONG Entry0Hi,
01239 IN ULONG Selector1,
01240 IN ULONG Entry1Low,
01241 IN ULONG Entry1Hi
01242 )
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
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
01279
01280
01281
01282
01283
01284
01285
if ((Selector0 & 0xFFFF0000) || (Selector1 & 0xFFFF0000)) {
01286
return STATUS_INVALID_LDT_DESCRIPTOR;
01287 }
01288
01289
01290
01291 Selector0 = Selector0 & ~(RPL_MASK | SELECTOR_TABLE_INDEX);
01292 Selector1 = Selector1 & ~(RPL_MASK | SELECTOR_TABLE_INDEX);
01293
01294
01295
01296
01297
01298
01299
if (Selector0) {
01300
01301
01302 Base = ((Entry0Low & 0xFFFF0000) >> 16) + ((Entry0Hi & 0xFF) << 16)
01303 + (Entry0Hi & 0xFF000000);
01304
01305 Limit = (Entry0Low & 0xFFFF) + (Entry0Hi & 0xF0000);
01306
01307
01308
01309
01310
if (Entry0Hi &
DESCRIPTOR_GRAN) {
01311 Limit = (Limit << 12) | 0xFFF;
01312 }
01313
01314
01315
01316
01317
01318
if (Entry0Hi &
DESCRIPTOR_NP) {
01319
01320
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
01331
01332
01333
01334
01335
if (Entry0Hi &
DESCRIPTOR_TYPEDPL) {
01336
01337
01338
if (!(Entry0Hi &
DESCRIPTOR_SYSTEM)) {
01339
return STATUS_INVALID_LDT_DESCRIPTOR;
01340 }
01341
01342
01343
if ((Entry0Hi &
DESCRIPTOR_CONFORM) ==
DESCRIPTOR_CONFORM) {
01344
return STATUS_INVALID_LDT_DESCRIPTOR;
01345 }
01346
01347
01348
if ((Entry0Hi &
DESCRIPTOR_DPL) !=
DESCRIPTOR_DPL) {
01349
return STATUS_INVALID_LDT_DESCRIPTOR;
01350 }
01351 }
01352 }
01353
01354
01355
01356
01357
01358
if (Selector1) {
01359
01360
01361 Base = ((Entry1Low & 0xFFFF0000) >> 16) + ((Entry1Hi & 0xFF) << 16)
01362 + (Entry1Hi & 0xFF000000);
01363
01364 Limit = (Entry1Low & 0xFFFF) + (Entry1Hi & 0xF0000);
01365
01366
01367
01368
01369
if (Entry1Hi &
DESCRIPTOR_GRAN) {
01370 Limit = (Limit << 12) | 0xFFF;
01371 }
01372
01373
01374
01375
01376
01377
if (Entry1Hi &
DESCRIPTOR_NP) {
01378
01379
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
01389
01390
01391
01392
01393
if (Entry1Hi &
DESCRIPTOR_TYPEDPL) {
01394
01395
01396
if (!(Entry1Hi &
DESCRIPTOR_SYSTEM)) {
01397
return STATUS_INVALID_LDT_DESCRIPTOR;
01398 }
01399
01400
01401
if ((Entry1Hi &
DESCRIPTOR_CONFORM) ==
DESCRIPTOR_CONFORM) {
01402
return STATUS_INVALID_LDT_DESCRIPTOR;
01403 }
01404
01405
01406
if ((Entry1Hi &
DESCRIPTOR_DPL) !=
DESCRIPTOR_DPL) {
01407
return STATUS_INVALID_LDT_DESCRIPTOR;
01408 }
01409 }
01410 }
01411
01412
01413
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
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
01442
01443
01444
01445
01446
if (ProcessLdtInformation) {
01447
01448
01449
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
01482
01483 }
else if (ProcessLdtInformation->AllocatedSize >= LdtSize) {
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
Ke386SetLdtProcess(
01497 &(Process->
Pcb),
01498
NULL,
01499 0
L
01500 );
01501
01502
01503
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
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
01534
01535 }
01536 }
01537
01538
01539
01540
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 = 0
L;
01555 ProcessLdtInformation->AllocatedSize = 0
L;
01556 ProcessLdtInformation->Ldt =
NULL;
01557 }
01558
01559
01560
01561
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
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
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
01648
01649
01650
Ke386SetLdtProcess(
01651 &(Process->
Pcb),
01652 ProcessLdtInformation->Ldt,
01653 ProcessLdtInformation->Size
01654 );
01655
01656
01657
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 }