00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "mi.h"
00024
00025
#if DBG
00026
PEPROCESS MmWatchProcess;
00027
VOID MmFooBar(VOID);
00028
#endif // DBG
00029
00030 HARDWARE_PTE
00031
MiFlushTbAndCapture(
00032 IN
PMMPTE PtePointer,
00033 IN HARDWARE_PTE TempPte,
00034 IN
PMMPFN Pfn1
00035 );
00036
00037 ULONG
00038
MiSetProtectionOnTransitionPte (
00039 IN
PMMPTE PointerPte,
00040 IN ULONG ProtectionMask
00041 );
00042
00043
MMPTE
00044
MiCaptureSystemPte (
00045 IN
PMMPTE PointerProtoPte,
00046 IN
PEPROCESS Process
00047 );
00048
00049
#if PFN_CONSISTENCY
00050
VOID
00051 MiSetOriginalPteProtection (
00052 IN
PMMPFN Pfn1,
00053 IN ULONG ProtectionMask
00054 )
00055 #endif
00056
00057 extern CCHAR
MmReadWrite[32];
00058
00059
#ifdef ALLOC_PRAGMA
00060
#pragma alloc_text(PAGE,NtProtectVirtualMemory)
00061
#pragma alloc_text(PAGE,MiProtectVirtualMemory)
00062
#pragma alloc_text(PAGE,MiSetProtectionOnSection)
00063
#pragma alloc_text(PAGE,MiGetPageProtection)
00064
#pragma alloc_text(PAGE,MiChangeNoAccessForkPte)
00065
#endif
00066
00067
00068
NTSTATUS
00069 NtProtectVirtualMemory(
00070 IN HANDLE ProcessHandle,
00071 IN OUT PVOID *BaseAddress,
00072 IN OUT PSIZE_T RegionSize,
00073 IN ULONG NewProtect,
00074 OUT PULONG OldProtect
00075 )
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 {
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
PEPROCESS Process;
00176
KPROCESSOR_MODE PreviousMode;
00177
NTSTATUS Status;
00178 ULONG Attached =
FALSE;
00179 PVOID CapturedBase;
00180 SIZE_T CapturedRegionSize;
00181 ULONG ProtectionMask;
00182
00183 ULONG LastProtect;
00184
00185
PAGED_CODE();
00186
00187
00188
00189
00190
00191
try {
00192 ProtectionMask =
MiMakeProtectionMask (NewProtect);
00193 } except (
EXCEPTION_EXECUTE_HANDLER) {
00194
return GetExceptionCode();
00195 }
00196
00197 PreviousMode = KeGetPreviousMode();
00198
00199
if (PreviousMode !=
KernelMode) {
00200
00201
00202
00203
00204
00205
try {
00206
00207
ProbeForWritePointer (BaseAddress);
00208
ProbeForWriteUlong_ptr (RegionSize);
00209
ProbeForWriteUlong (OldProtect);
00210
00211
00212
00213
00214
00215 CapturedBase = *BaseAddress;
00216 CapturedRegionSize = *RegionSize;
00217
00218 } except (
EXCEPTION_EXECUTE_HANDLER) {
00219
00220
00221
00222
00223
00224
00225
00226
return GetExceptionCode();
00227 }
00228
00229 }
else {
00230
00231
00232
00233
00234
00235 CapturedRegionSize = *RegionSize;
00236 CapturedBase = *BaseAddress;
00237 }
00238
00239
#if DBG
00240
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
00241
if ( !MmWatchProcess ) {
00242
DbgPrint(
"protectvm process handle %lx base address %lx size %lx protect %lx\n",
00243 ProcessHandle, CapturedBase, CapturedRegionSize, NewProtect);
00244 }
00245 }
00246
#endif
00247
00248
00249
00250
00251
00252
00253
if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {
00254
00255
00256
00257
00258
00259
return STATUS_INVALID_PARAMETER_2;
00260 }
00261
00262
if ((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)CapturedBase <
00263 CapturedRegionSize) {
00264
00265
00266
00267
00268
00269
return STATUS_INVALID_PARAMETER_3;
00270 }
00271
00272
if (CapturedRegionSize == 0) {
00273
return STATUS_INVALID_PARAMETER_3;
00274 }
00275
00276
Status =
ObReferenceObjectByHandle ( ProcessHandle,
00277 PROCESS_VM_OPERATION,
00278
PsProcessType,
00279 PreviousMode,
00280 (PVOID *)&Process,
00281
NULL );
00282
00283
if (!
NT_SUCCESS(
Status)) {
00284
return Status;
00285 }
00286
00287
00288
00289
00290
00291
00292
if (
PsGetCurrentProcess() != Process) {
00293
KeAttachProcess (&Process->Pcb);
00294 Attached =
TRUE;
00295 }
00296
00297
Status =
MiProtectVirtualMemory (Process,
00298 &CapturedBase,
00299 &CapturedRegionSize,
00300 NewProtect,
00301 &LastProtect);
00302
00303
00304
if (Attached) {
00305
KeDetachProcess();
00306 }
00307
00308
ObDereferenceObject (Process);
00309
00310
00311
00312
00313
00314
00315
try {
00316
00317
00318
00319
00320
00321
00322
00323
00324
if (PreviousMode !=
KernelMode) {
00325
00326
ProbeForWritePointer (BaseAddress);
00327
ProbeForWriteUlong_ptr (RegionSize);
00328
ProbeForWriteUlong (OldProtect);
00329 }
00330
00331 *RegionSize = CapturedRegionSize;
00332 *BaseAddress = CapturedBase;
00333 *OldProtect = LastProtect;
00334
00335 } except (
EXCEPTION_EXECUTE_HANDLER) {
00336 NOTHING;
00337 }
00338
00339
return Status;
00340 }
00341
00342
00343
NTSTATUS
00344 MiProtectVirtualMemory (
00345 IN
PEPROCESS Process,
00346 IN PVOID *BaseAddress,
00347 IN PSIZE_T RegionSize,
00348 IN ULONG NewProtect,
00349 IN PULONG LastProtect
00350 )
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 {
00386
PMMVAD FoundVad;
00387 PVOID StartingAddress;
00388 PVOID EndingAddress;
00389 PVOID CapturedBase;
00390 SIZE_T CapturedRegionSize;
00391
NTSTATUS Status;
00392 ULONG Attached;
00393
PMMPTE PointerPte;
00394
PMMPTE LastPte;
00395
PMMPTE PointerPde;
00396
PMMPTE PointerPpe;
00397
PMMPTE PointerProtoPte;
00398
PMMPTE LastProtoPte;
00399
PMMPFN Pfn1;
00400 ULONG CapturedOldProtect;
00401 ULONG ProtectionMask;
00402
MMPTE TempPte;
00403
MMPTE PteContents;
00404
MMPTE PreviousPte;
00405 ULONG Locked;
00406 PVOID Va;
00407 ULONG DoAgain;
00408 ULONG Waited;
00409 PVOID UsedPageTableHandle;
00410 PVOID UsedPageDirectoryHandle;
00411 ULONG WorkingSetIndex;
00412
#if defined(_MIALT4K_)
00413
PVOID OriginalBase;
00414 SIZE_T OriginalRegionSize;
00415 ULONG OriginalProtectionMask;
00416 PVOID StartingAddressFor4k;
00417 PVOID EndingAddressFor4k;
00418 SIZE_T CapturedRegionSizeFor4k;
00419 ULONG CapturedOldProtectFor4k;
00420 BOOLEAN EmulationFor4kPage =
FALSE;
00421
#endif
00422
00423 Attached =
FALSE;
00424 Locked =
FALSE;
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 CapturedBase = *BaseAddress;
00435 CapturedRegionSize = *RegionSize;
00436
00437
#if defined(_MIALT4K_)
00438
OriginalBase = CapturedBase;
00439 OriginalRegionSize = CapturedRegionSize;
00440
00441
if (Process->Wow64Process !=
NULL) {
00442
00443 StartingAddressFor4k = (PVOID)
PAGE_4K_ALIGN(OriginalBase);
00444
00445 EndingAddressFor4k = (PVOID)(((ULONG_PTR)OriginalBase +
00446 OriginalRegionSize - 1) | (
PAGE_4K - 1));
00447
00448 CapturedRegionSizeFor4k = (ULONG_PTR)EndingAddressFor4k -
00449 (ULONG_PTR)StartingAddressFor4k + 1
L;
00450
00451 OriginalProtectionMask =
MiMakeProtectionMask(NewProtect);
00452
00453 EmulationFor4kPage =
TRUE;
00454
00455 }
00456
#endif
00457
00458
try {
00459 ProtectionMask =
MiMakeProtectionMask (NewProtect);
00460 } except (
EXCEPTION_EXECUTE_HANDLER) {
00461
return GetExceptionCode();
00462 }
00463
00464
LOCK_WS_AND_ADDRESS_SPACE (Process);
00465
00466
00467
00468
00469
00470
if (Process->AddressSpaceDeleted != 0) {
00471
Status = STATUS_PROCESS_IS_TERMINATING;
00472
goto ErrorFound;
00473 }
00474
00475 EndingAddress = (PVOID)(((ULONG_PTR)CapturedBase +
00476 CapturedRegionSize - 1
L) | (
PAGE_SIZE - 1
L));
00477 StartingAddress = (PVOID)
PAGE_ALIGN(CapturedBase);
00478 FoundVad =
MiCheckForConflictingVad (StartingAddress, EndingAddress);
00479
00480
if (FoundVad == (
PMMVAD)
NULL) {
00481
00482
00483
00484
00485
00486
00487
Status = STATUS_CONFLICTING_ADDRESSES;
00488
goto ErrorFound;
00489 }
00490
00491
00492
00493
00494
00495
00496
if ((
MI_VA_TO_VPN (StartingAddress) < FoundVad->
StartingVpn) ||
00497 (
MI_VA_TO_VPN (EndingAddress) > FoundVad->
EndingVpn)) {
00498
00499
00500
00501
00502
00503
00504
Status = STATUS_CONFLICTING_ADDRESSES;
00505
goto ErrorFound;
00506 }
00507
00508
if (FoundVad->
u.VadFlags.UserPhysicalPages == 1) {
00509
00510
00511
00512
00513
00514
Status = STATUS_CONFLICTING_ADDRESSES;
00515
goto ErrorFound;
00516 }
00517
00518
if (FoundVad->
u.VadFlags.PhysicalMapping == 1) {
00519
00520
00521
00522
00523
00524
00525
Status = STATUS_CONFLICTING_ADDRESSES;
00526
goto ErrorFound;
00527 }
00528
00529
if (FoundVad->
u.VadFlags.NoChange == 1) {
00530
00531
00532
00533
00534
00535
00536
00537
Status =
MiCheckSecuredVad (FoundVad,
00538 CapturedBase,
00539 CapturedRegionSize,
00540 ProtectionMask);
00541
00542
if (!
NT_SUCCESS (
Status)) {
00543
goto ErrorFound;
00544 }
00545 }
00546
#if defined(_MIALT4K_)
00547
else if (EmulationFor4kPage ==
TRUE) {
00548
00549
00550
00551
00552 NewProtect =
MiMakeProtectForNativePage(StartingAddressFor4k,
00553 NewProtect,
00554 Process);
00555
00556 ProtectionMask =
MiMakeProtectionMask (NewProtect);
00557 }
00558
#endif
00559
00560
if (FoundVad->
u.VadFlags.PrivateMemory == 0) {
00561
00562
00563
00564
00565
00566
00567
if (NewProtect & PAGE_NOCACHE) {
00568
00569
00570
00571
00572
00573
Status = STATUS_INVALID_PARAMETER_4;
00574
goto ErrorFound;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
if ((FoundVad->
ControlArea->
u.Flags.File == 0) ||
00585 (FoundVad->
ControlArea->
u.Flags.Image == 1)) {
00586
00587 PointerProtoPte =
MiGetProtoPteAddress (FoundVad,
00588
MI_VA_TO_VPN (StartingAddress));
00589 LastProtoPte =
MiGetProtoPteAddress (FoundVad,
00590
MI_VA_TO_VPN (EndingAddress));
00591
00592
00593
00594
00595
00596
00597
00598
UNLOCK_WS_UNSAFE (Process);
00599
ExAcquireFastMutexUnsafe (&
MmSectionCommitMutex);
00600
00601
while (PointerProtoPte <= LastProtoPte) {
00602
00603
00604
00605
00606
00607
00608
if (PointerProtoPte->
u.Long == 0) {
00609
00610
00611
00612
00613
00614
ExReleaseFastMutexUnsafe (&
MmSectionCommitMutex);
00615
Status = STATUS_NOT_COMMITTED;
00616
UNLOCK_ADDRESS_SPACE (Process);
00617
goto ErrorFoundNoWs;
00618 }
00619 PointerProtoPte += 1;
00620 }
00621
00622
00623
00624
00625
00626
00627
ExReleaseFastMutexUnsafe (&
MmSectionCommitMutex);
00628
00629
00630
00631
00632
00633
00634
LOCK_WS_UNSAFE (Process);
00635 }
00636
00637
#if defined(_MIALT4K_)
00638
00639
00640
00641
00642
00643
00644
if (EmulationFor4kPage ==
TRUE) {
00645
00646
00647
00648
00649
00650
UNLOCK_WS_UNSAFE (Process);
00651
00652
00653
00654
00655
00656 CapturedOldProtectFor4k =
00657
MiQueryProtectionFor4kPage(StartingAddressFor4k, Process);
00658
00659
if (CapturedOldProtectFor4k != 0) {
00660
00661 CapturedOldProtectFor4k =
00662
MI_CONVERT_FROM_PTE_PROTECTION(CapturedOldProtectFor4k);
00663
00664 }
00665
00666
00667
00668
00669
00670
if ((FoundVad->
u.VadFlags.ImageMap == 1) ||
00671 (FoundVad->
u2.VadFlags2.CopyOnWrite == 1)) {
00672
00673 OriginalProtectionMask |=
MM_PROTECTION_COPY_MASK;
00674
00675 }
00676
00677
MiProtectFor4kPage (StartingAddressFor4k,
00678 CapturedRegionSizeFor4k,
00679 OriginalProtectionMask,
00680
ALT_CHANGE,
00681 Process);
00682
00683
LOCK_WS_UNSAFE (Process);
00684 }
00685
#endif
00686
00687
try {
00688 Locked =
MiSetProtectionOnSection ( Process,
00689 FoundVad,
00690 StartingAddress,
00691 EndingAddress,
00692 NewProtect,
00693 &CapturedOldProtect,
00694
FALSE );
00695
00696 } except (
EXCEPTION_EXECUTE_HANDLER) {
00697
00698
Status = GetExceptionCode();
00699
goto ErrorFound;
00700 }
00701 }
else {
00702
00703
00704
00705
00706
00707
00708
if ((NewProtect & PAGE_WRITECOPY) ||
00709 (NewProtect & PAGE_EXECUTE_WRITECOPY)) {
00710
00711
00712
00713
00714
00715
Status = STATUS_INVALID_PARAMETER_4;
00716
goto ErrorFound;
00717 }
00718
00719
00720
00721
00722
00723
00724
if ( !
MiIsEntireRangeCommitted(StartingAddress,
00725 EndingAddress,
00726 FoundVad,
00727 Process)) {
00728
00729
00730
00731
00732
00733
00734
Status = STATUS_NOT_COMMITTED;
00735
goto ErrorFound;
00736 }
00737
00738
#if defined(_MIALT4K_)
00739
00740
00741
00742
00743
00744
00745
if (EmulationFor4kPage ==
TRUE) {
00746
00747
00748
00749
00750
00751
UNLOCK_WS_UNSAFE (Process);
00752
00753
00754
00755
00756
00757 CapturedOldProtectFor4k =
00758
MiQueryProtectionFor4kPage(StartingAddressFor4k, Process);
00759
00760
if (CapturedOldProtectFor4k != 0) {
00761
00762 CapturedOldProtectFor4k =
00763
MI_CONVERT_FROM_PTE_PROTECTION(CapturedOldProtectFor4k);
00764
00765 }
00766
00767
00768
00769
00770
00771
MiProtectFor4kPage (StartingAddressFor4k,
00772 CapturedRegionSizeFor4k,
00773 OriginalProtectionMask,
00774
ALT_CHANGE,
00775 Process);
00776
00777
LOCK_WS_UNSAFE (Process);
00778 }
00779
#endif
00780
00781
00782
00783
00784
00785 PointerPpe =
MiGetPpeAddress (StartingAddress);
00786 PointerPde =
MiGetPdeAddress (StartingAddress);
00787 PointerPte =
MiGetPteAddress (StartingAddress);
00788 LastPte =
MiGetPteAddress (EndingAddress);
00789
00790
#if defined (_WIN64)
00791
MiMakePpeExistAndMakeValid (PointerPpe, Process,
FALSE);
00792
if (PointerPde->
u.Long == 0) {
00793 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00794
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00795 }
00796
#endif
00797
00798
MiMakePdeExistAndMakeValid(PointerPde, Process,
FALSE);
00799
00800
00801
00802
00803
00804
if (PointerPte->
u.Long != 0) {
00805
00806 CapturedOldProtect =
MiGetPageProtection (PointerPte, Process);
00807
00808
00809
00810
00811
00812
#if defined (_WIN64)
00813
MiMakePpeExistAndMakeValid (PointerPpe, Process,
FALSE);
00814
if (PointerPde->
u.Long == 0) {
00815 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00816
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00817 }
00818
#endif
00819
00820 (
VOID)
MiMakePdeExistAndMakeValid(PointerPde, Process,
FALSE);
00821
00822 }
else {
00823
00824
00825
00826
00827
00828 CapturedOldProtect =
00829
MI_CONVERT_FROM_PTE_PROTECTION(FoundVad->
u.VadFlags.Protection);
00830 }
00831
00832
00833
00834
00835
00836
00837
while (PointerPte <= LastPte) {
00838
00839
if (
MiIsPteOnPdeBoundary (PointerPte)) {
00840
00841 PointerPde =
MiGetPteAddress (PointerPte);
00842 PointerPpe =
MiGetPdeAddress (PointerPte);
00843
00844
#if defined (_WIN64)
00845
MiMakePpeExistAndMakeValid (PointerPpe, Process,
FALSE);
00846
if (PointerPde->
u.Long == 0) {
00847 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
00848
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
00849 }
00850
#endif
00851
00852
MiMakePdeExistAndMakeValid(PointerPde, Process,
FALSE);
00853 }
00854
00855 PteContents = *PointerPte;
00856
00857
if (PteContents.
u.Long == 0) {
00858
00859
00860
00861
00862
00863
00864
00865
00866 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (
MiGetVirtualAddressMappedByPte (PointerPte));
00867
00868
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
00869 }
00870
00871
if (PteContents.
u.Hard.Valid == 1) {
00872
00873
00874
00875
00876
00877
00878 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
00879
00880
if (Pfn1->
u3.e1.PrototypePte == 1) {
00881
00882
00883
00884
00885
00886
00887
MiCopyOnWrite (
MiGetVirtualAddressMappedByPte (PointerPte),
00888 PointerPte);
00889
00890
00891
00892
00893
00894
00895
00896
do {
00897
00898 (
VOID)
MiDoesPpeExistAndMakeValid (
MiGetPteAddress (PointerPde),
00899 Process,
00900
FALSE,
00901 &Waited);
00902
00903 Waited = 0;
00904
00905 (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde,
00906 Process,
00907
FALSE,
00908 &Waited);
00909
00910 }
while (Waited != 0);
00911
00912
00913
00914
00915
00916
continue;
00917 }
else {
00918
00919
00920
00921
00922
00923
00924
00925
if ((NewProtect & PAGE_NOACCESS) ||
00926 (NewProtect & PAGE_GUARD)) {
00927
00928
00929
00930
00931
00932 Locked =
MiRemovePageFromWorkingSet (PointerPte,
00933 Pfn1,
00934 &Process->Vm);
00935
00936
00937
continue;
00938 }
else {
00939
00940
#if PFN_CONSISTENCY
00941
MiSetOriginalPteProtection (Pfn1, ProtectionMask);
00942
#else
00943
Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
00944
#endif
00945
MI_MAKE_VALID_PTE (TempPte,
00946 PointerPte->
u.Hard.PageFrameNumber,
00947 ProtectionMask,
00948 PointerPte);
00949
00950 WorkingSetIndex =
MI_GET_WORKING_SET_FROM_PTE (&PteContents);
00951
MI_SET_PTE_IN_WORKING_SET (&TempPte, WorkingSetIndex);
00952
00953
00954
00955
00956
00957
00958 PreviousPte.
u.Flush =
MiFlushTbAndCapture (PointerPte,
00959 TempPte.
u.Flush,
00960 Pfn1);
00961 }
00962 }
00963 }
else {
00964
00965
if (PteContents.
u.Soft.Prototype == 1) {
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
00980
00981 DoAgain =
TRUE;
00982
00983
while (PteContents.
u.Hard.Valid == 0) {
00984
00985
UNLOCK_WS_UNSAFE (Process);
00986
00987
try {
00988
00989 *(
volatile ULONG *)Va;
00990 } except (
EXCEPTION_EXECUTE_HANDLER) {
00991
00992
if (GetExceptionCode() ==
00993 STATUS_ACCESS_VIOLATION) {
00994
00995
00996
00997
00998
00999 DoAgain =
MiChangeNoAccessForkPte (PointerPte,
01000 ProtectionMask);
01001 }
else if (GetExceptionCode() ==
01002 STATUS_IN_PAGE_ERROR) {
01003
01004
01005
01006
01007 PointerPte += 1;
01008 DoAgain =
TRUE;
01009
01010
if (PointerPte > LastPte) {
01011
LOCK_WS_UNSAFE (Process);
01012
break;
01013 }
01014 }
01015 }
01016
01017
LOCK_WS_UNSAFE (Process);
01018
01019
do {
01020
01021 (
VOID)
MiDoesPpeExistAndMakeValid (
MiGetPteAddress (PointerPde),
01022 Process,
01023
FALSE,
01024 &Waited);
01025
01026 Waited = 0;
01027
01028 (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde,
01029 Process,
01030
FALSE,
01031 &Waited);
01032
01033 }
while (Waited != 0);
01034
01035 PteContents = *(
volatile MMPTE *)PointerPte;
01036 }
01037
01038
if (DoAgain) {
01039
continue;
01040 }
01041
01042 }
else {
01043
01044
if (PteContents.
u.Soft.Transition == 1) {
01045
01046
if (
MiSetProtectionOnTransitionPte (
01047 PointerPte,
01048 ProtectionMask)) {
01049
continue;
01050 }
01051 }
else {
01052
01053
01054
01055
01056
01057 PointerPte->
u.Soft.Protection = ProtectionMask;
01058
ASSERT (PointerPte->u.Long != 0);
01059 }
01060 }
01061 }
01062 PointerPte += 1;
01063 }
01064 }
01065
01066
01067
01068
01069
01070
#if defined(_MIALT4K_)
01071
01072
if (EmulationFor4kPage ==
TRUE) {
01073
01074 StartingAddress = StartingAddressFor4k;
01075
01076 EndingAddress = EndingAddressFor4k;
01077
01078
if (CapturedOldProtectFor4k != 0) {
01079
01080
01081
01082
01083
01084
01085 CapturedOldProtect = CapturedOldProtectFor4k;
01086
01087 }
01088 }
01089
#endif
01090
01091 *RegionSize = (PCHAR)EndingAddress - (PCHAR)StartingAddress + 1
L;
01092 *BaseAddress = StartingAddress;
01093 *LastProtect = CapturedOldProtect;
01094
01095
if (Locked) {
01096
Status = STATUS_WAS_UNLOCKED;
01097 }
else {
01098
Status = STATUS_SUCCESS;
01099 }
01100
01101 ErrorFound:
01102
UNLOCK_WS_AND_ADDRESS_SPACE (Process);
01103
01104 ErrorFoundNoWs:
01105
return Status;
01106 }
01107
01108
01109 ULONG
01110 MiSetProtectionOnSection (
01111 IN
PEPROCESS Process,
01112 IN
PMMVAD FoundVad,
01113 IN PVOID StartingAddress,
01114 IN PVOID EndingAddress,
01115 IN ULONG NewProtect,
01116 OUT PULONG CapturedOldProtect,
01117 IN ULONG DontCharge
01118 )
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160 {
01161
PMMPTE PointerPte;
01162
PMMPTE LastPte;
01163
PMMPTE PointerPde;
01164
PMMPTE PointerPpe;
01165
PMMPTE PointerProtoPte;
01166
PMMPFN Pfn1;
01167
MMPTE TempPte;
01168
MMPTE PreviousPte;
01169 ULONG Locked;
01170 ULONG ProtectionMask;
01171 ULONG ProtectionMaskNotCopy;
01172 ULONG NewProtectionMask;
01173
MMPTE PteContents;
01174 ULONG
Index;
01175 PULONG Va;
01176 ULONG WriteCopy;
01177 ULONG DoAgain;
01178 ULONG Waited;
01179 SIZE_T QuotaCharge;
01180 PVOID UsedPageTableHandle;
01181 PVOID UsedPageDirectoryHandle;
01182 ULONG WorkingSetIndex;
01183
01184
PAGED_CODE();
01185
01186 Locked =
FALSE;
01187 WriteCopy =
FALSE;
01188 QuotaCharge = 0;
01189
01190
01191
01192
01193
01194
ASSERT (FoundVad->u.VadFlags.PrivateMemory == 0);
01195
01196
if ((FoundVad->u.VadFlags.ImageMap == 1) ||
01197 (FoundVad->u2.VadFlags2.CopyOnWrite == 1)) {
01198
01199
if (NewProtect & PAGE_READWRITE) {
01200 NewProtect &= ~PAGE_READWRITE;
01201 NewProtect |= PAGE_WRITECOPY;
01202 }
01203
01204
if (NewProtect & PAGE_EXECUTE_READWRITE) {
01205 NewProtect &= ~PAGE_EXECUTE_READWRITE;
01206 NewProtect |= PAGE_EXECUTE_WRITECOPY;
01207 }
01208 }
01209
01210 ProtectionMask =
MiMakeProtectionMask (NewProtect);
01211
01212
01213
01214
01215
01216 ProtectionMaskNotCopy = ProtectionMask;
01217
if ((ProtectionMask &
MM_COPY_ON_WRITE_MASK) ==
MM_COPY_ON_WRITE_MASK) {
01218 WriteCopy =
TRUE;
01219 ProtectionMaskNotCopy &= ~
MM_PROTECTION_COPY_MASK;
01220 }
01221
01222
#if defined(_MIALT4K_)
01223
01224
if ((Process->Wow64Process !=
NULL) &&
01225 (FoundVad->u.VadFlags.ImageMap == 0) &&
01226 (FoundVad->u2.VadFlags2.CopyOnWrite == 0) &&
01227 (WriteCopy)) {
01228
01229
NTSTATUS status;
01230
01231 status = MiSetCopyPagesFor4kPage(Process,
01232 &FoundVad,
01233 &StartingAddress,
01234 &EndingAddress,
01235 ProtectionMask);
01236
01237
if (status != STATUS_SUCCESS) {
01238
ExRaiseStatus (status);
01239 }
01240
01241 }
01242
01243
#endif
01244
01245 PointerPpe =
MiGetPpeAddress (StartingAddress);
01246 PointerPde =
MiGetPdeAddress (StartingAddress);
01247 PointerPte =
MiGetPteAddress (StartingAddress);
01248 LastPte =
MiGetPteAddress (EndingAddress);
01249
01250
#if defined (_WIN64)
01251
MiMakePpeExistAndMakeValid (PointerPpe, Process,
FALSE);
01252
if (PointerPde->
u.Long == 0) {
01253 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
01254
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
01255 }
01256
#endif
01257
01258
MiMakePdeExistAndMakeValid(PointerPde, Process,
FALSE);
01259
01260
01261
01262
01263
01264
if (PointerPte->
u.Long != 0) {
01265
01266 *CapturedOldProtect =
MiGetPageProtection (PointerPte, Process);
01267
01268
01269
01270
01271
01272 PointerPpe =
MiGetPteAddress (PointerPde);
01273
01274
do {
01275
01276 (
VOID)
MiDoesPpeExistAndMakeValid (PointerPpe, Process,
FALSE, &Waited);
01277 Waited = 0;
01278
01279 (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde, Process,
FALSE, &Waited);
01280 }
while (Waited != 0);
01281
01282 }
else {
01283
01284
01285
01286
01287
01288
if (FoundVad->u.VadFlags.ImageMap == 0) {
01289
01290
01291
01292
01293
01294 *CapturedOldProtect =
01295
MI_CONVERT_FROM_PTE_PROTECTION(FoundVad->u.VadFlags.Protection);
01296 }
else {
01297
01298
01299
01300
01301
01302
01303 PointerProtoPte =
MiGetProtoPteAddress (FoundVad,
01304
MI_VA_TO_VPN (
01305
MiGetVirtualAddressMappedByPte (PointerPte)));
01306
01307 TempPte =
MiCaptureSystemPte (PointerProtoPte, Process);
01308
01309 *CapturedOldProtect =
MiGetPageProtection (&TempPte,
01310 Process);
01311
01312
01313
01314
01315
01316 PointerPpe =
MiGetPteAddress (PointerPde);
01317
01318
do {
01319
01320 (
VOID)
MiDoesPpeExistAndMakeValid(PointerPpe, Process,
FALSE, &Waited);
01321 Waited = 0;
01322
01323 (
VOID)
MiDoesPdeExistAndMakeValid(PointerPde, Process,
FALSE, &Waited);
01324 }
while (Waited != 0);
01325 }
01326 }
01327
01328
01329
01330
01331
01332
01333
01334
01335
if (WriteCopy) {
01336
01337
01338
01339
01340
01341
01342
while (PointerPte <= LastPte) {
01343
01344
if (
MiIsPteOnPdeBoundary (PointerPte)) {
01345
01346 PointerPde =
MiGetPteAddress (PointerPte);
01347 PointerPpe =
MiGetPteAddress (PointerPde);
01348
01349
do {
01350
01351
while (!
MiDoesPpeExistAndMakeValid(PointerPpe, Process,
FALSE, &Waited)) {
01352
01353
01354
01355
01356
01357
01358
01359 PointerPpe += 1;
01360 PointerPde =
MiGetVirtualAddressMappedByPte (PointerPpe);
01361 PointerProtoPte = PointerPte;
01362 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
01363
01364
if (PointerPte > LastPte) {
01365 QuotaCharge += 1 + LastPte - PointerProtoPte;
01366
goto Done;
01367 }
01368 QuotaCharge += PointerPte - PointerProtoPte;
01369 }
01370
01371 Waited = 0;
01372
01373
while (!
MiDoesPdeExistAndMakeValid(PointerPde, Process,
FALSE, &Waited)) {
01374
01375
01376
01377
01378
01379
01380
01381 PointerPde += 1;
01382 PointerProtoPte = PointerPte;
01383 PointerPpe =
MiGetPteAddress (PointerPde);
01384 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
01385
01386
if (PointerPte > LastPte) {
01387 QuotaCharge += 1 + LastPte - PointerProtoPte;
01388
goto Done;
01389 }
01390 QuotaCharge += PointerPte - PointerProtoPte;
01391
#if defined (_WIN64)
01392
if (
MiIsPteOnPdeBoundary (PointerPde)) {
01393 Waited = 1;
01394
break;
01395 }
01396
#endif
01397
}
01398 }
while (Waited != 0);
01399 }
01400
01401 PteContents = *PointerPte;
01402
01403
if (PteContents.
u.Long == 0) {
01404
01405
01406
01407
01408
01409 QuotaCharge += 1;
01410
01411 }
else if ((PteContents.
u.Hard.Valid == 1) &&
01412 (PteContents.
u.Hard.CopyOnWrite == 0)) {
01413
01414
01415
01416
01417
01418 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
01419
01420
if (Pfn1->
u3.e1.PrototypePte == 1) {
01421 QuotaCharge += 1;
01422 }
01423 }
else {
01424
01425
if (PteContents.
u.Soft.Prototype == 1) {
01426
01427
01428
01429
01430
01431
01432
if (PteContents.
u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED) {
01433
01434
01435
01436
01437
01438
if (!
MI_IS_PTE_PROTECTION_COPY_WRITE(PteContents.
u.Soft.Protection)) {
01439 QuotaCharge += 1;
01440 }
01441 }
else {
01442
01443
01444
01445
01446
01447
01448 QuotaCharge += 1;
01449 }
01450 }
01451 }
01452 PointerPte += 1;
01453 }
01454
01455 Done:
01456 NOTHING;
01457
01458
01459
01460
01461
01462
if (!DontCharge) {
01463
MiChargePageFileQuota (QuotaCharge, Process);
01464
01465
if (Process->CommitChargeLimit) {
01466
if (Process->CommitCharge + QuotaCharge > Process->CommitChargeLimit) {
01467
MiReturnPageFileQuota (QuotaCharge, Process);
01468
if (Process->Job) {
01469
PsReportProcessMemoryLimitViolation ();
01470 }
01471
ExRaiseStatus (STATUS_COMMITMENT_LIMIT);
01472 }
01473 }
01474
if (Process->JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
01475
if (
PsChangeJobMemoryUsage(QuotaCharge) ==
FALSE) {
01476
MiReturnPageFileQuota (QuotaCharge, Process);
01477
ExRaiseStatus (STATUS_COMMITMENT_LIMIT);
01478 }
01479 }
01480
01481
if (
MiChargeCommitment (QuotaCharge, Process) ==
FALSE) {
01482
if (Process->JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
01483
01484
01485
01486
01487
01488
01489
01490 Process->CommitCharge += QuotaCharge;
01491
PsChangeJobMemoryUsage(-(SSIZE_T)QuotaCharge);
01492 Process->CommitCharge -= QuotaCharge;
01493 }
01494
MiReturnPageFileQuota (QuotaCharge, Process);
01495
ExRaiseStatus STATUS_COMMITMENT_LIMIT;
01496 }
01497
01498
01499
01500
01501
01502
MM_TRACK_COMMIT (
MM_DBG_COMMIT_SET_PROTECTION, QuotaCharge);
01503 FoundVad->u.VadFlags.CommitCharge += QuotaCharge;
01504 Process->CommitCharge += QuotaCharge;
01505
if (Process->CommitCharge > Process->CommitChargePeak) {
01506 Process->CommitChargePeak = Process->CommitCharge;
01507 }
01508 }
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522 PointerPpe =
MiGetPpeAddress (StartingAddress);
01523 PointerPde =
MiGetPdeAddress (StartingAddress);
01524 PointerPte =
MiGetPteAddress (StartingAddress);
01525
01526
do {
01527
01528
MiDoesPpeExistAndMakeValid (PointerPpe, Process,
FALSE, &Waited);
01529
01530 Waited = 0;
01531
01532
MiDoesPdeExistAndMakeValid (PointerPde, Process,
FALSE, &Waited);
01533
01534 }
while (Waited != 0);
01535
01536 QuotaCharge = 0;
01537
01538
while (PointerPte <= LastPte) {
01539
01540
if (
MiIsPteOnPdeBoundary (PointerPte)) {
01541 PointerPde =
MiGetPteAddress (PointerPte);
01542 PointerPpe =
MiGetPdeAddress (PointerPte);
01543
01544
#if defined (_WIN64)
01545
MiMakePpeExistAndMakeValid (PointerPpe, Process,
FALSE);
01546
if (PointerPde->
u.Long == 0) {
01547 UsedPageDirectoryHandle =
MI_GET_USED_PTES_HANDLE (PointerPte);
01548
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle);
01549 }
01550
#endif
01551
01552
MiMakePdeExistAndMakeValid (PointerPde, Process,
FALSE);
01553 }
01554
01555 PteContents = *PointerPte;
01556
01557
if (PteContents.
u.Long == 0) {
01558
01559
01560
01561
01562
01563
01564 TempPte =
PrototypePte;
01565 TempPte.
u.Soft.Protection = ProtectionMask;
01566
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
01567
01568
01569
01570
01571
01572
01573
01574 UsedPageTableHandle =
MI_GET_USED_PTES_HANDLE (
MiGetVirtualAddressMappedByPte (PointerPte));
01575
01576
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle);
01577
01578 }
else if (PteContents.
u.Hard.Valid == 1) {
01579
01580
01581
01582
01583
01584
01585 NewProtectionMask = ProtectionMask;
01586
01587 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
01588
01589
if ((NewProtect & PAGE_NOACCESS) ||
01590 (NewProtect & PAGE_GUARD)) {
01591
01592 Locked =
MiRemovePageFromWorkingSet (PointerPte,
01593 Pfn1,
01594 &Process->Vm );
01595
continue;
01596
01597 }
else {
01598
01599
if (Pfn1->
u3.e1.PrototypePte == 1) {
01600
01601
01602
01603
01604
01605
01606 Va = (PULONG)
MiGetVirtualAddressMappedByPte (PointerPte);
01607
Index =
MiLocateWsle ((PVOID)Va,
MmWorkingSetList,
01608 Pfn1->
u1.WsIndex);
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
if (Pfn1->
PteAddress !=
01619
MiGetProtoPteAddress (FoundVad,
01620
MI_VA_TO_VPN ((PVOID)Va))) {
01621
01622
01623
01624
01625
01626
01627
MiCopyOnWrite ((PVOID)Va, PointerPte);
01628
01629
if (WriteCopy) {
01630 QuotaCharge += 1;
01631 }
01632
01633
01634
01635
01636
01637
01638 PointerPpe =
MiGetPteAddress (PointerPde);
01639
01640
do {
01641
01642 (
VOID)
MiDoesPpeExistAndMakeValid (PointerPpe,
01643 Process,
01644
FALSE,
01645 &Waited);
01646
01647 Waited = 0;
01648
01649 (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde,
01650 Process,
01651
FALSE,
01652 &Waited);
01653
01654 }
while (Waited != 0);
01655
01656
01657
01658
01659
01660
continue;
01661
01662 }
else {
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
if ((!WriteCopy) && (PteContents.
u.Hard.CopyOnWrite == 1)) {
01674 QuotaCharge += 1;
01675 }
01676
01677
MmWsle[
Index].
u1.e1.Protection = ProtectionMask;
01678
MmWsle[
Index].
u1.e1.SameProtectAsProto = 0;
01679 }
01680
01681 }
else {
01682
01683
01684
01685
01686
01687
01688
#if PFN_CONSISTENCY
01689
MiSetOriginalPteProtection (Pfn1, ProtectionMaskNotCopy);
01690
#else
01691
Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMaskNotCopy;
01692
#endif
01693
NewProtectionMask = ProtectionMaskNotCopy;
01694 }
01695
01696
MI_MAKE_VALID_PTE (TempPte,
01697 PteContents.
u.Hard.PageFrameNumber,
01698 NewProtectionMask,
01699 PointerPte);
01700
01701 WorkingSetIndex =
MI_GET_WORKING_SET_FROM_PTE (&PteContents);
01702
01703
MI_SET_PTE_IN_WORKING_SET (&TempPte, WorkingSetIndex);
01704 }
01705
01706
01707
01708
01709
01710
01711 PreviousPte.
u.Flush =
MiFlushTbAndCapture (PointerPte,
01712 TempPte.
u.Flush,
01713 Pfn1);
01714 }
else {
01715
01716
if (PteContents.
u.Soft.Prototype == 1) {
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726 Va = (PULONG)
MiGetVirtualAddressMappedByPte (PointerPte);
01727
01728
if ((PteContents.
u.Soft.PageFileHigh !=
MI_PTE_LOOKUP_NEEDED) &&
01729 (
MiPteToProto (PointerPte) !=
01730
MiGetProtoPteAddress (FoundVad,
01731
MI_VA_TO_VPN ((PVOID)Va)))) {
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 DoAgain =
TRUE;
01746
01747
while (PteContents.
u.Hard.Valid == 0) {
01748
01749
UNLOCK_WS_UNSAFE (Process);
01750
01751
try {
01752
01753 *(
volatile ULONG *)Va;
01754 } except (
EXCEPTION_EXECUTE_HANDLER) {
01755
01756
if (GetExceptionCode() !=
01757 STATUS_GUARD_PAGE_VIOLATION) {
01758
01759
01760
01761
01762
01763 DoAgain =
MiChangeNoAccessForkPte (PointerPte,
01764 ProtectionMask);
01765 }
01766 }
01767
01768 PointerPpe =
MiGetPteAddress (PointerPde);
01769
01770
LOCK_WS_UNSAFE (Process);
01771
01772
do {
01773
01774 (
VOID)
MiDoesPpeExistAndMakeValid (PointerPpe,
01775 Process,
01776
FALSE,
01777 &Waited);
01778
01779 Waited = 0;
01780
01781 (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde,
01782 Process,
01783
FALSE,
01784 &Waited);
01785
01786 }
while (Waited != 0);
01787
01788 PteContents = *(
volatile MMPTE *)PointerPte;
01789 }
01790
01791
if (DoAgain) {
01792
continue;
01793 }
01794
01795 }
else {
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
if ((!WriteCopy) &&
01806 (PteContents.
u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED)) {
01807
if (
MI_IS_PTE_PROTECTION_COPY_WRITE(PteContents.
u.Soft.Protection)) {
01808 QuotaCharge += 1;
01809 }
01810
01811 }
01812
01813
01814
01815
01816
01817
01818
01819
MI_WRITE_INVALID_PTE (PointerPte,
PrototypePte);
01820 PointerPte->u.Soft.Protection = ProtectionMask;
01821 }
01822
01823 }
else {
01824
01825
if (PteContents.
u.Soft.Transition == 1) {
01826
01827
01828
01829
01830
01831
if (
MiSetProtectionOnTransitionPte (
01832 PointerPte,
01833 ProtectionMaskNotCopy)) {
01834
continue;
01835 }
01836
01837 }
else {
01838
01839
01840
01841
01842
01843 PointerPte->u.Soft.Protection = ProtectionMaskNotCopy;
01844 }
01845 }
01846 }
01847
01848 PointerPte += 1;
01849 }
01850
01851
01852
01853
01854
01855
if ((QuotaCharge > 0) && (!DontCharge)) {
01856
01857
MiReturnCommitment (QuotaCharge);
01858
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PROTECTION, QuotaCharge);
01859
MiReturnPageFileQuota (QuotaCharge, Process);
01860
01861
ASSERT (QuotaCharge <= FoundVad->u.VadFlags.CommitCharge);
01862
01863 FoundVad->u.VadFlags.CommitCharge -= QuotaCharge;
01864
if (Process->JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
01865
PsChangeJobMemoryUsage(-(SSIZE_T)QuotaCharge);
01866 }
01867 Process->CommitCharge -= QuotaCharge;
01868 }
01869
01870
return Locked;
01871 }
01872
01873 ULONG
01874 MiGetPageProtection (
01875 IN
PMMPTE PointerPte,
01876 IN
PEPROCESS Process
01877 )
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903 {
01904
01905
MMPTE PteContents;
01906
MMPTE ProtoPteContents;
01907
PMMPFN Pfn1;
01908
PMMPTE ProtoPteAddress;
01909 PVOID Va;
01910 ULONG
Index;
01911
01912
PAGED_CODE();
01913
01914 PteContents = *PointerPte;
01915
01916
if ((PteContents.
u.Soft.Valid == 0) && (PteContents.
u.Soft.Prototype == 1)) {
01917
01918
01919
01920
01921
01922
01923
if (
MI_IS_PTE_PROTOTYPE(PointerPte) ||
01924
#ifdef _X86_
01925
(
MiNumberOfExtraSystemPdes && (PointerPte >= (
PMMPTE)
KSTACK_POOL_START && PointerPte < (
PMMPTE)(
KSTACK_POOL_START +
MiNumberOfExtraSystemPdes *
MM_VA_MAPPED_BY_PDE))) ||
01926
#endif
01927
(PteContents.
u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED)) {
01928
01929
01930
01931
01932
01933
return MI_CONVERT_FROM_PTE_PROTECTION (
01934 PteContents.
u.Soft.Protection);
01935 }
01936
01937 ProtoPteAddress =
MiPteToProto (PointerPte);
01938
01939
01940
01941
01942
01943 ProtoPteContents =
MiCaptureSystemPte (ProtoPteAddress, Process);
01944
01945
01946
01947
01948
01949
01950
01951 PteContents =
MiCaptureSystemPte (PointerPte, Process);
01952 }
01953
01954
if ((PteContents.
u.Soft.Valid == 0) && (PteContents.
u.Soft.Prototype == 1)) {
01955
01956
01957
01958
01959
01960
01961
if (ProtoPteContents.
u.Hard.Valid == 1) {
01962
01963
01964
01965
01966
01967
01968 Pfn1 =
MI_PFN_ELEMENT (ProtoPteContents.
u.Hard.PageFrameNumber);
01969
return MI_CONVERT_FROM_PTE_PROTECTION(
01970 Pfn1->
OriginalPte.
u.Soft.Protection);
01971
01972 }
else {
01973
01974
01975
01976
01977
01978
01979
return MI_CONVERT_FROM_PTE_PROTECTION (
01980 ProtoPteContents.
u.Soft.Protection);
01981 }
01982 }
01983
01984
if (PteContents.
u.Hard.Valid == 1) {
01985
01986
01987
01988
01989
01990
01991
01992
01993 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
01994
01995
if ((Pfn1->
u3.e1.PrototypePte == 0) ||
01996
#ifdef _X86_
01997
(
MiNumberOfExtraSystemPdes && (PointerPte >= (
PMMPTE)
KSTACK_POOL_START && PointerPte < (
PMMPTE)(
KSTACK_POOL_START +
MiNumberOfExtraSystemPdes *
MM_VA_MAPPED_BY_PDE))) ||
01998
#endif
01999
(
MI_IS_PTE_PROTOTYPE(PointerPte))) {
02000
02001
02002
02003
02004
02005
02006
02007
return MI_CONVERT_FROM_PTE_PROTECTION(
02008 Pfn1->
OriginalPte.
u.Soft.Protection);
02009 }
02010
02011
02012
02013
02014
02015 Va = (PULONG)
MiGetVirtualAddressMappedByPte (PointerPte);
02016
Index =
MiLocateWsle ((PVOID)Va,
MmWorkingSetList,
02017 Pfn1->
u1.WsIndex);
02018
02019
return MI_CONVERT_FROM_PTE_PROTECTION (
MmWsle[
Index].u1.e1.Protection);
02020 }
02021
02022
02023
02024
02025
02026
02027
return MI_CONVERT_FROM_PTE_PROTECTION (PteContents.
u.Soft.Protection);
02028
02029 }
02030
02031 ULONG
02032 MiChangeNoAccessForkPte (
02033 IN
PMMPTE PointerPte,
02034 IN ULONG ProtectionMask
02035 )
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060 {
02061
PAGED_CODE();
02062
02063
if (ProtectionMask ==
MM_NOACCESS) {
02064
02065
02066
02067
02068
02069
return TRUE;
02070 }
02071
02072 PointerPte->u.Proto.ReadOnly = 1;
02073
02074
return FALSE;
02075 }
02076
02077
02078 HARDWARE_PTE
02079 MiFlushTbAndCapture(
02080 IN
PMMPTE PointerPte,
02081 IN HARDWARE_PTE TempPte,
02082 IN
PMMPFN Pfn1
02083 )
02084
02085
02086
02087 {
02088
MMPTE PreviousPte;
02089 KIRQL OldIrql;
02090
PEPROCESS Process;
02091 PVOID VirtualAddress;
02092
02093
02094
02095
02096
02097
02098
LOCK_PFN (OldIrql);
02099
02100 PreviousPte.
u.Flush =
KeFlushSingleTb (
02101
MiGetVirtualAddressMappedByPte (PointerPte),
02102
FALSE,
02103
FALSE,
02104 (PHARDWARE_PTE)PointerPte,
02105 TempPte);
02106
02107
ASSERT (PreviousPte.
u.Hard.Valid == 1);
02108
02109
02110
02111
02112
02113
02114
02115
MI_CAPTURE_DIRTY_BIT_TO_PFN (&PreviousPte, Pfn1);
02116
02117
02118
02119
02120
02121
02122
02123
if (
MiActiveWriteWatch != 0) {
02124
if ((Pfn1->u3.e1.PrototypePte == 0) &&
02125 (
MI_IS_PTE_DIRTY(PreviousPte))) {
02126
02127 Process =
PsGetCurrentProcess();
02128
02129
if (Process->
Vm.
u.Flags.WriteWatch == 1) {
02130
02131
02132
02133
02134
02135
02136
02137 VirtualAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
02138
MiCaptureWriteWatchDirtyBit (Process, VirtualAddress);
02139 }
02140 }
02141 }
02142
#if DBG
02143
else {
02144 Process =
PsGetCurrentProcess();
02145
ASSERT (Process->
Vm.
u.Flags.WriteWatch == 0);
02146 }
02147
#endif
02148
02149
UNLOCK_PFN (OldIrql);
02150
return PreviousPte.
u.Flush;
02151 }
02152
02153 ULONG
02154 MiSetProtectionOnTransitionPte (
02155 IN
PMMPTE PointerPte,
02156 IN ULONG ProtectionMask
02157 )
02158
02159
02160
02161 {
02162 KIRQL OldIrql;
02163
MMPTE PteContents;
02164
PMMPFN Pfn1;
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
LOCK_PFN (OldIrql);
02176
02177
02178
02179
02180
02181 PteContents = *(
volatile MMPTE *)PointerPte;
02182
02183
if ((PteContents.
u.Soft.Prototype == 0) &&
02184 (PointerPte->u.Soft.Transition == 1)) {
02185
02186 Pfn1 =
MI_PFN_ELEMENT (
02187 PteContents.
u.Trans.PageFrameNumber);
02188
02189 Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
02190 PointerPte->u.Soft.Protection = ProtectionMask;
02191
UNLOCK_PFN (OldIrql);
02192
return FALSE;
02193 }
02194
02195
02196
02197
02198
02199
UNLOCK_PFN (OldIrql);
02200
return TRUE;
02201 }
02202
02203
MMPTE
02204 MiCaptureSystemPte (
02205 IN
PMMPTE PointerProtoPte,
02206 IN
PEPROCESS Process
02207 )
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232 {
02233
MMPTE TempPte;
02234 KIRQL OldIrql;
02235
02236
LOCK_PFN (OldIrql);
02237
MiMakeSystemAddressValidPfnWs (PointerProtoPte, Process);
02238 TempPte = *PointerProtoPte;
02239
UNLOCK_PFN (OldIrql);
02240
return TempPte;
02241 }
02242
02243
NTSTATUS
02244 MiCheckSecuredVad (
02245 IN
PMMVAD Vad,
02246 IN PVOID Base,
02247 IN SIZE_T Size,
02248 IN ULONG ProtectionMask
02249 )
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279 {
02280 PVOID
End;
02281 PLIST_ENTRY Next;
02282
PMMSECURE_ENTRY Entry;
02283
NTSTATUS Status = STATUS_SUCCESS;
02284
02285
End = (PVOID)((PCHAR)Base +
Size);
02286
02287
if (ProtectionMask <
MM_SECURE_DELETE_CHECK) {
02288
if ((Vad->u.VadFlags.NoChange == 1) &&
02289 (Vad->u2.VadFlags2.SecNoChange == 1) &&
02290 (Vad->u.VadFlags.Protection != ProtectionMask)) {
02291
02292
02293
02294
02295
02296
02297
Status = STATUS_INVALID_PAGE_PROTECTION;
02298
goto done;
02299 }
02300 }
else {
02301
02302
02303
02304
02305
02306
02307 ProtectionMask = 0;
02308 }
02309
02310
if (Vad->u2.VadFlags2.OneSecured) {
02311
02312
if (((ULONG_PTR)Base <= Vad->u3.Secured.EndVpn) &&
02313 ((ULONG_PTR)
End >= Vad->u3.Secured.StartVpn)) {
02314
02315
02316
02317
02318
02319
if (ProtectionMask &
MM_GUARD_PAGE) {
02320
Status = STATUS_INVALID_PAGE_PROTECTION;
02321
goto done;
02322 }
02323
02324
if (Vad->u2.VadFlags2.ReadOnly) {
02325
if (
MmReadWrite[ProtectionMask] < 10) {
02326
Status = STATUS_INVALID_PAGE_PROTECTION;
02327
goto done;
02328 }
02329 }
else {
02330
if (
MmReadWrite[ProtectionMask] < 11) {
02331
Status = STATUS_INVALID_PAGE_PROTECTION;
02332
goto done;
02333 }
02334 }
02335 }
02336
02337 }
else if (Vad->u2.VadFlags2.MultipleSecured) {
02338
02339 Next = Vad->u3.List.Flink;
02340
do {
02341 Entry = CONTAINING_RECORD( Next,
02342
MMSECURE_ENTRY,
02343
List);
02344
02345
if (((ULONG_PTR)Base <= Entry->
EndVpn) &&
02346 ((ULONG_PTR)
End >= Entry->
StartVpn)) {
02347
02348
02349
02350
02351
02352
if (ProtectionMask &
MM_GUARD_PAGE) {
02353
Status = STATUS_INVALID_PAGE_PROTECTION;
02354
goto done;
02355 }
02356
02357
if (Entry->
u2.VadFlags2.ReadOnly) {
02358
if (
MmReadWrite[ProtectionMask] < 10) {
02359
Status = STATUS_INVALID_PAGE_PROTECTION;
02360
goto done;
02361 }
02362 }
else {
02363
if (
MmReadWrite[ProtectionMask] < 11) {
02364
Status = STATUS_INVALID_PAGE_PROTECTION;
02365
goto done;
02366 }
02367 }
02368 }
02369 Next = Entry->
List.Flink;
02370 }
while (Entry->
List.Flink != &Vad->u3.List);
02371 }
02372
02373 done:
02374
return Status;
02375 }
02376
02377
#ifdef PFN_CONSISTENCY
02378
02379 BOOLEAN MiCheckPfnState =
FALSE;
02380
02381
VOID
02382 MiMapInPfnDatabase (
02383 VOID
02384 )
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406 {
02407 PFN_NUMBER i;
02408
PMMPTE PointerPte;
02409
02410
MM_PFN_LOCK_ASSERT();
02411
02412
ASSERT (MiPfnStartPte);
02413
02414 PointerPte = MiPfnStartPte;
02415
02416
for (i = 0; i < MiPfnPtes; i += 1) {
02417
02418
02419
02420
02421
02422
if (PointerPte->
u.Hard.Valid == 1) {
02423
#if defined (_ALPHA_)
02424
if (MiCheckPfnState ==
TRUE) {
02425
ASSERT (PointerPte->
u.Hard.Dirty == 0);
02426 }
02427 PointerPte->
u.Hard.Dirty = 1;
02428
#elif defined (NT_UP)
02429
if (MiCheckPfnState ==
TRUE) {
02430
ASSERT (PointerPte->
u.Hard.Write == 0);
02431 }
02432 PointerPte->
u.Hard.Write = 1;
02433
#else
02434
if (MiCheckPfnState ==
TRUE) {
02435
ASSERT (PointerPte->
u.Hard.Writable == 0);
02436 }
02437 PointerPte->
u.Hard.Writable = 1;
02438
#endif
02439
}
02440 PointerPte += 1;
02441 }
02442
KeFlushEntireTb (TRUE, TRUE);
02443 }
02444
02445
02446
VOID
02447 MiUnMapPfnDatabase (
02448 VOID
02449 )
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471 {
02472 PFN_NUMBER i;
02473
PMMPTE PointerPte;
02474
02475
MM_PFN_LOCK_ASSERT();
02476
02477
ASSERT (MiPfnStartPte);
02478
02479
if (MiPfnProtectionEnabled ==
FALSE) {
02480
02481
02482
02483
return;
02484 }
02485
02486 PointerPte = MiPfnStartPte;
02487
02488
for (i = 0; i < MiPfnPtes; i += 1) {
02489
02490
02491
02492
02493
02494
if (PointerPte->
u.Hard.Valid == 1) {
02495
#if defined (_ALPHA_)
02496
if (MiCheckPfnState ==
TRUE) {
02497
ASSERT (PointerPte->
u.Hard.Dirty == 1);
02498 }
02499 PointerPte->
u.Hard.Dirty = 0;
02500
#elif defined (NT_UP)
02501
if (MiCheckPfnState ==
TRUE) {
02502
ASSERT (PointerPte->
u.Hard.Write == 1);
02503 }
02504 PointerPte->
u.Hard.Write = 0;
02505
#else
02506
if (MiCheckPfnState ==
TRUE) {
02507
ASSERT (PointerPte->
u.Hard.Writable == 1);
02508 }
02509 PointerPte->
u.Hard.Writable = 0;
02510
#endif
02511
PointerPte += 1;
02512 }
02513 }
02514
KeFlushEntireTb (TRUE, TRUE);
02515 }
02516
02517
VOID
02518 MiSetOriginalPteProtection (
02519 IN
PMMPFN Pfn1,
02520 IN ULONG ProtectionMask
02521 )
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546 {
02547 KIRQL OldIrql;
02548
02549
LOCK_PFN (OldIrql);
02550 Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
02551
UNLOCK_PFN (OldIrql);
02552 }
02553
02554
VOID
02555 MiSetModified (
02556 IN
PMMPFN Pfn1,
02557 IN ULONG Dirty
02558 )
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582 {
02583 KIRQL OldIrql;
02584
02585
LOCK_PFN (OldIrql);
02586 Pfn1->u3.e1.Modified = Dirty;
02587
UNLOCK_PFN (OldIrql);
02588 }
02589
02590
#endif // PFN_CONSISTENCY