MmIsAddressValid

Тема в разделе "WASM.NT.KERNEL", создана пользователем agent007, 19 мар 2007.

  1. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Надо разбирать исходники этой функции, чтобы дать точный ответ
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Разбирайся:

    Код (Text):
    1. VOID
    2. MmProbeAndLockPages (
    3.      IN OUT PMDL MemoryDescriptorList,
    4.      IN KPROCESSOR_MODE AccessMode,
    5.      IN LOCK_OPERATION Operation
    6.      )
    7.  
    8. /*++
    9.  
    10. Routine Description:
    11.  
    12.     This routine probes the specified pages, makes the pages resident and
    13.     locks the physical pages mapped by the virtual pages in memory.  The
    14.     Memory descriptor list is updated to describe the physical pages.
    15.  
    16. Arguments:
    17.  
    18.     MemoryDescriptorList - Supplies a pointer to a Memory Descriptor List
    19.                             (MDL). The supplied MDL must supply a virtual
    20.                             address, byte offset and length field.  The
    21.                             physical page portion of the MDL is updated when
    22.                             the pages are locked in memory.
    23.  
    24.     AccessMode - Supplies the access mode in which to probe the arguments.
    25.                  One of KernelMode or UserMode.
    26.  
    27.     Operation - Supplies the operation type.  One of IoReadAccess, IoWriteAccess
    28.                 or IoModifyAccess.
    29.  
    30. Return Value:
    31.  
    32.     None - exceptions are raised.
    33.  
    34. Environment:
    35.  
    36.     Kernel mode.  APC_LEVEL and below for pagable addresses,
    37.                   DISPATCH_LEVEL and below for non-pagable addresses.
    38.  
    39. --*/
    40.  
    41. {
    42.     PPFN_NUMBER Page;
    43.     MMPTE PteContents;
    44.     PMMPTE PointerPte;
    45.     PMMPTE PointerPde;
    46.     PMMPTE PointerPpe;
    47.     PVOID Va;
    48.     PVOID EndVa;
    49.     PVOID AlignedVa;
    50.     PMMPFN Pfn1;
    51.     PFN_NUMBER PageFrameIndex;
    52.     PEPROCESS CurrentProcess;
    53.     KIRQL OldIrql;
    54.     PFN_NUMBER NumberOfPagesToLock;
    55.     PFN_NUMBER NumberOfPagesSpanned;
    56.     NTSTATUS status;
    57.     NTSTATUS ProbeStatus;
    58.     PETHREAD Thread;
    59.     ULONG SavedState;
    60.     LOGICAL AddressIsPhysical;
    61.     PLIST_ENTRY NextEntry;
    62.     PMI_PHYSICAL_VIEW PhysicalView;
    63.     PCHAR StartVa;
    64.     PVOID CallingAddress;
    65.     PVOID CallersCaller;
    66.  
    67. #if !defined (_X86_)
    68.     CallingAddress = (PVOID)_ReturnAddress();
    69.     CallersCaller = (PVOID)0;
    70. #endif
    71.  
    72. #if DBG
    73.     if (MiPrintLockedPages != 0) {
    74.         MiVerifyLockedPageCharges ();
    75.     }
    76. #endif
    77.  
    78.     ASSERT (MemoryDescriptorList->ByteCount != 0);
    79.     ASSERT (((ULONG)MemoryDescriptorList->ByteOffset & ~(PAGE_SIZE - 1)) == 0);
    80.  
    81.     Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
    82.  
    83.     ASSERT (((ULONG_PTR)MemoryDescriptorList->StartVa & (PAGE_SIZE - 1)) == 0);
    84.     AlignedVa = (PVOID)MemoryDescriptorList->StartVa;
    85.  
    86.     ASSERT ((MemoryDescriptorList->MdlFlags & (
    87.                     MDL_PAGES_LOCKED |
    88.                     MDL_MAPPED_TO_SYSTEM_VA |
    89.                     MDL_SOURCE_IS_NONPAGED_POOL |
    90.                     MDL_PARTIAL |
    91.                     MDL_IO_SPACE)) == 0);
    92.  
    93.     Va = (PCHAR)AlignedVa + MemoryDescriptorList->ByteOffset;
    94.     StartVa = Va;
    95.  
    96.     PointerPte = MiGetPteAddress (Va);
    97.  
    98.     //
    99.     // Endva is one byte past the end of the buffer, if ACCESS_MODE is not
    100.     // kernel, make sure the EndVa is in user space AND the byte count
    101.     // does not cause it to wrap.
    102.     //
    103.  
    104.     EndVa = (PVOID)((PCHAR)Va + MemoryDescriptorList->ByteCount);
    105.  
    106.     if ((AccessMode != KernelMode) &&
    107.         ((EndVa > (PVOID)MM_USER_PROBE_ADDRESS) || (Va >= EndVa))) {
    108.         *Page = MM_EMPTY_LIST;
    109.         MI_INSTRUMENT_PROBE_RAISES(0);
    110.         ExRaiseStatus (STATUS_ACCESS_VIOLATION);
    111.         return;
    112.     }
    113.  
    114.     //
    115.     // There is an optimization which could be performed here.  If
    116.     // the operation is for WriteAccess and the complete page is
    117.     // being modified, we can remove the current page, if it is not
    118.     // resident, and substitute a demand zero page.
    119.     // Note, that after analysis by marking the thread and then
    120.     // noting if a page read was done, this rarely occurs.
    121.     //
    122.  
    123.     MemoryDescriptorList->Process = (PEPROCESS)NULL;
    124.  
    125.     Thread = PsGetCurrentThread ();
    126.  
    127.     if (!MI_IS_PHYSICAL_ADDRESS(Va)) {
    128.  
    129.         AddressIsPhysical = FALSE;
    130.         ProbeStatus = STATUS_SUCCESS;
    131.  
    132.         NumberOfPagesToLock = COMPUTE_PAGES_SPANNED (Va,
    133.                                        MemoryDescriptorList->ByteCount);
    134.  
    135.         ASSERT (NumberOfPagesToLock != 0);
    136.  
    137.         NumberOfPagesSpanned = NumberOfPagesToLock;
    138.  
    139.         PointerPpe = MiGetPpeAddress (Va);
    140.         PointerPde = MiGetPdeAddress (Va);
    141.  
    142.         MmSavePageFaultReadAhead (Thread, &SavedState);
    143.         MmSetPageFaultReadAhead (Thread, (ULONG)(NumberOfPagesToLock - 1));
    144.  
    145.         try {
    146.  
    147.             do {
    148.  
    149.                 *Page = MM_EMPTY_LIST;
    150.  
    151.                 //
    152.                 // Make sure the page is resident.
    153.                 //
    154.  
    155.                 *(volatile CHAR *)Va;
    156.  
    157.                 if ((Operation != IoReadAccess) &&
    158.                     (Va <= MM_HIGHEST_USER_ADDRESS)) {
    159.  
    160.                     //
    161.                     // Probe for write access as well.
    162.                     //
    163.  
    164.                     ProbeForWriteChar ((PCHAR)Va);
    165.                 }
    166.  
    167.                 NumberOfPagesToLock -= 1;
    168.  
    169.                 MmSetPageFaultReadAhead (Thread, (ULONG)(NumberOfPagesToLock - 1));
    170.                 Va = (PVOID)(((ULONG_PTR)(PCHAR)Va + PAGE_SIZE) & ~(PAGE_SIZE - 1));
    171.                 Page += 1;
    172.             } while (Va < EndVa);
    173.  
    174.             ASSERT (NumberOfPagesToLock == 0);
    175.  
    176.         } except (EXCEPTION_EXECUTE_HANDLER) {
    177.             ProbeStatus = GetExceptionCode();
    178.         }
    179.  
    180.         //
    181.         // We may still fault again below but it's generally rare.
    182.         // Restore this thread's normal fault behavior now.
    183.         //
    184.  
    185.         MmResetPageFaultReadAhead (Thread, SavedState);
    186.  
    187.         if (ProbeStatus != STATUS_SUCCESS) {
    188.             MI_INSTRUMENT_PROBE_RAISES(1);
    189.             ExRaiseStatus (ProbeStatus);
    190.             return;
    191.         }
    192.     }
    193.     else {
    194.         AddressIsPhysical = TRUE;
    195.         *Page = MM_EMPTY_LIST;
    196.     }
    197.  
    198.     Va = AlignedVa;
    199.     Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
    200.  
    201.     //
    202.     // Indicate that this is a write operation.
    203.     //
    204.  
    205.     if (Operation != IoReadAccess) {
    206.         MemoryDescriptorList->MdlFlags |= MDL_WRITE_OPERATION;
    207.     } else {
    208.         MemoryDescriptorList->MdlFlags &= ~(MDL_WRITE_OPERATION);
    209.     }
    210.  
    211.     //
    212.     // Acquire the PFN database lock.
    213.     //
    214.  
    215.     LOCK_PFN2 (OldIrql);
    216.  
    217.     if (Va <= MM_HIGHEST_USER_ADDRESS) {
    218.  
    219.         //
    220.         // These are addresses with user space, check to see if the
    221.         // working set size will allow these pages to be locked.
    222.         //
    223.  
    224.         ASSERT (NumberOfPagesSpanned != 0);
    225.  
    226.         CurrentProcess = PsGetCurrentProcess ();
    227.  
    228.         //
    229.         // Check for a transfer to/from a physical VAD - no reference counts
    230.         // may be modified for these pages.
    231.         //
    232.  
    233.         NextEntry = CurrentProcess->PhysicalVadList.Flink;
    234.         while (NextEntry != &CurrentProcess->PhysicalVadList) {
    235.  
    236.             PhysicalView = CONTAINING_RECORD(NextEntry,
    237.                                              MI_PHYSICAL_VIEW,
    238.                                              ListEntry);
    239.  
    240.             if ((PhysicalView->Vad->u.VadFlags.UserPhysicalPages == 0) &&
    241.                 (PhysicalView->Vad->u.VadFlags.PhysicalMapping == 0)) {
    242.                 NextEntry = NextEntry->Flink;
    243.                 continue;
    244.             }
    245.  
    246.             if (StartVa < PhysicalView->StartVa) {
    247.  
    248.                 if ((PCHAR)EndVa - 1 >= PhysicalView->StartVa) {
    249.  
    250.                     //
    251.                     // The range encompasses a physical VAD.  This is not
    252.                     // allowed.
    253.                     //
    254.  
    255.                     UNLOCK_PFN2 (OldIrql);
    256.                     MI_INSTRUMENT_PROBE_RAISES(2);
    257.                     ExRaiseStatus (STATUS_ACCESS_VIOLATION);
    258.                     return;
    259.                 }
    260.  
    261.                 NextEntry = NextEntry->Flink;
    262.                 continue;
    263.             }
    264.  
    265.             if (StartVa <= PhysicalView->EndVa) {
    266.  
    267.                 //
    268.                 // Ensure that the entire range lies within the VAD.
    269.                 //
    270.  
    271.                 if ((PCHAR)EndVa - 1 > PhysicalView->EndVa) {
    272.  
    273.                     //
    274.                     // The range goes past the end of the VAD - not allowed.
    275.                     //
    276.  
    277.                     UNLOCK_PFN2 (OldIrql);
    278.                     MI_INSTRUMENT_PROBE_RAISES(3);
    279.                     ExRaiseStatus (STATUS_ACCESS_VIOLATION);
    280.                     return;
    281.                 }
    282.  
    283.                 if (PhysicalView->Vad->u.VadFlags.UserPhysicalPages == 1) {
    284.  
    285.                     //
    286.                     // All the PTEs must still be checked and reference
    287.                     // counts bumped on the pages.  Just don't charge
    288.                     // against the working set.
    289.                     //
    290.  
    291.                     NextEntry = NextEntry->Flink;
    292.                     continue;
    293.                 }
    294.  
    295.                 //
    296.                 // The range lies within a physical VAD.
    297.                 //
    298.  
    299.                 if (Operation != IoReadAccess) {
    300.  
    301.                     //
    302.                     // Ensure the VAD is writable.  Changing individual PTE
    303.                     // protections in a physical VAD is not allowed.
    304.                     //
    305.  
    306.                     if ((PhysicalView->Vad->u.VadFlags.Protection & MM_READWRITE) == 0) {
    307.                         UNLOCK_PFN2 (OldIrql);
    308.                         MI_INSTRUMENT_PROBE_RAISES(4);
    309.                         ExRaiseStatus (STATUS_ACCESS_VIOLATION);
    310.                         return;
    311.                     }
    312.                 }
    313.  
    314.                 //
    315.                 // Don't charge page locking for this transfer as it is all
    316.                 // physical, just initialize the MDL.  Note the pages do not
    317.                 // have to be physically contiguous, so the frames must be
    318.                 // extracted from the PTEs.
    319.                 //
    320.  
    321.                 MemoryDescriptorList->MdlFlags |= (MDL_PHYSICAL_VIEW | MDL_PAGES_LOCKED);
    322.                 MemoryDescriptorList->Process = CurrentProcess;
    323.  
    324.                 do {
    325.                     PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
    326.                     *Page = PageFrameIndex;
    327.                     Page += 1;
    328.                     PointerPte += 1;
    329.                     Va = (PVOID)((PCHAR)Va + PAGE_SIZE);
    330.                 } while (Va < EndVa);
    331.  
    332.                 UNLOCK_PFN2 (OldIrql);
    333.                 return;
    334.             }
    335.             NextEntry = NextEntry->Flink;
    336.         }
    337.  
    338.         CurrentProcess->NumberOfLockedPages += NumberOfPagesSpanned;
    339.  
    340.         MemoryDescriptorList->Process = CurrentProcess;
    341.     }
    342.  
    343.     MemoryDescriptorList->MdlFlags |= MDL_PAGES_LOCKED;
    344.  
    345.     do {
    346.  
    347.         if (AddressIsPhysical == TRUE) {
    348.  
    349.             //
    350.             // On certain architectures, virtual addresses
    351.             // may be physical and hence have no corresponding PTE.
    352.             //
    353.  
    354.             PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (Va);
    355.  
    356.         } else {
    357.  
    358. #if defined (_WIN64)
    359.             while ((PointerPpe->u.Hard.Valid == 0) ||
    360.                    (PointerPde->u.Hard.Valid == 0) ||
    361.                    (PointerPte->u.Hard.Valid == 0))
    362. #else
    363.             while ((PointerPde->u.Hard.Valid == 0) ||
    364.                    (PointerPte->u.Hard.Valid == 0))
    365. #endif
    366.             {
    367.  
    368.                 //
    369.                 // PDE is not resident, release PFN lock touch the page and make
    370.                 // it appear.
    371.                 //
    372.  
    373.                 UNLOCK_PFN2 (OldIrql);
    374.  
    375.                 MmSetPageFaultReadAhead (Thread, 0);
    376.  
    377.                 status = MmAccessFault (FALSE, Va, KernelMode, (PVOID)0);
    378.  
    379.                 MmResetPageFaultReadAhead (Thread, SavedState);
    380.  
    381.                 if (!NT_SUCCESS(status)) {
    382.  
    383.                     //
    384.                     // An exception occurred.  Unlock the pages locked
    385.                     // so far.
    386.                     //
    387.  
    388. failure:
    389.                     if (MmTrackLockedPages == TRUE) {
    390.  
    391.                         //
    392.                         // Adjust the MDL length so that MmUnlockPages only
    393.                         // processes the part that was completed.
    394.                         //
    395.  
    396.                         ULONG PagesLocked;
    397.            
    398.                         PagesLocked = ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartVa,
    399.                                               MemoryDescriptorList->ByteCount);
    400.  
    401. #if defined (_X86_)
    402.                         RtlGetCallersAddress(&CallingAddress, &CallersCaller);
    403. #endif
    404.                         MiAddMdlTracker (MemoryDescriptorList,
    405.                                          CallingAddress,
    406.                                          CallersCaller,
    407.                                          PagesLocked,
    408.                                          0);
    409.                     }
    410.  
    411.                     MmUnlockPages (MemoryDescriptorList);
    412.  
    413.                     //
    414.                     // Raise an exception of access violation to the caller.
    415.                     //
    416.  
    417.                     MI_INSTRUMENT_PROBE_RAISES(7);
    418.                     ExRaiseStatus (status);
    419.                     return;
    420.                 }
    421.  
    422.                 LOCK_PFN2 (OldIrql);
    423.             }
    424.  
    425.             PteContents = *PointerPte;
    426.             ASSERT (PteContents.u.Hard.Valid == 1);
    427.  
    428.             if (Va <= MM_HIGHEST_USER_ADDRESS) {
    429.                 if (Operation != IoReadAccess) {
    430.  
    431.                     if ((PteContents.u.Long & MM_PTE_WRITE_MASK) == 0) {
    432.  
    433.                         //
    434.                         // The caller has made the page protection more
    435.                         // restrictive, this should never be done once the
    436.                         // request has been issued !  Rather than wading
    437.                         // through the PFN database entry to see if it
    438.                         // could possibly work out, give the caller an
    439.                         // access violation.
    440.                         //
    441.  
    442. #if DBG
    443.                         DbgPrint ("MmProbeAndLockPages: PTE %p %p changed\n",
    444.                             PointerPte,
    445.                             PteContents.u.Long);
    446.                         ASSERT (FALSE);
    447. #endif
    448.  
    449.                         UNLOCK_PFN2 (OldIrql);
    450.                         status = STATUS_ACCESS_VIOLATION;
    451.                         goto failure;
    452.                     }
    453.                 }
    454.             }
    455.  
    456.             PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
    457.         }
    458.  
    459.         if (PageFrameIndex > MmHighestPhysicalPage) {
    460.  
    461.             //
    462.             // This is an I/O space address don't allow operations
    463.             // on addresses not in the PFN database.
    464.             //
    465.  
    466.             MemoryDescriptorList->MdlFlags |= MDL_IO_SPACE;
    467.  
    468.         } else {
    469.             ASSERT ((MemoryDescriptorList->MdlFlags & MDL_IO_SPACE) == 0);
    470.  
    471.             Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    472.  
    473. #if PFN_CONSISTENCY
    474.             ASSERT(Pfn1->u3.e1.PageTablePage == 0);
    475. #endif
    476.  
    477.             //
    478.             // Check to make sure this page is not locked down an unusually
    479.             // high number of times.
    480.             //
    481.  
    482.             if (Pfn1->u3.e2.ReferenceCount >= MmReferenceCountCheck) {
    483.                 UNLOCK_PFN2 (OldIrql);
    484.                 ASSERT (FALSE);
    485.                 status = STATUS_WORKING_SET_QUOTA;
    486.                 goto failure;
    487.             }
    488.  
    489.             //
    490.             // Check to make sure the systemwide locked pages count is fluid.
    491.             //
    492.  
    493.             if (MI_NONPAGABLE_MEMORY_AVAILABLE() <= 0) {
    494.  
    495.                 //
    496.                 // If this page is for paged pool or privileged code/data,
    497.                 // then force it in.
    498.                 //
    499.  
    500.                 if ((Va > MM_HIGHEST_USER_ADDRESS) &&
    501.                     (!MI_IS_SYSTEM_CACHE_ADDRESS(Va))) {
    502.                     MI_INSTRUMENT_PROBE_RAISES(8);
    503.                     goto ok;
    504.                 }
    505.  
    506.                 MI_INSTRUMENT_PROBE_RAISES(5);
    507.                 UNLOCK_PFN2 (OldIrql);
    508.                 status = STATUS_WORKING_SET_QUOTA;
    509.                 goto failure;
    510.             }
    511.  
    512.             //
    513.             // Check to make sure any administrator-desired limit is obeyed.
    514.             //
    515.  
    516.             if (MmSystemLockPagesCount + 1 >= MmLockPagesLimit) {
    517.  
    518.                 //
    519.                 // If this page is for paged pool or privileged code/data,
    520.                 // then force it in.
    521.                 //
    522.  
    523.                 if ((Va > MM_HIGHEST_USER_ADDRESS) &&
    524.                     (!MI_IS_SYSTEM_CACHE_ADDRESS(Va))) {
    525.                     MI_INSTRUMENT_PROBE_RAISES(9);
    526.                     goto ok;
    527.                 }
    528.  
    529.                 MI_INSTRUMENT_PROBE_RAISES(6);
    530.                 UNLOCK_PFN2 (OldIrql);
    531.                 status = STATUS_WORKING_SET_QUOTA;
    532.                 goto failure;
    533.             }
    534.  
    535. ok:
    536.             MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 0);
    537.  
    538.             Pfn1->u3.e2.ReferenceCount += 1;
    539.         }
    540.  
    541.         *Page = PageFrameIndex;
    542.  
    543.         Page += 1;
    544.         PointerPte += 1;
    545.         if (MiIsPteOnPdeBoundary(PointerPte)) {
    546.             PointerPde += 1;
    547.             if (MiIsPteOnPpeBoundary(PointerPte)) {
    548.                 PointerPpe += 1;
    549.             }
    550.         }
    551.  
    552.         Va = (PVOID)((PCHAR)Va + PAGE_SIZE);
    553.     } while (Va < EndVa);
    554.  
    555.     UNLOCK_PFN2 (OldIrql);
    556.  
    557.     if ((MmTrackLockedPages == TRUE) && (AlignedVa <= MM_HIGHEST_USER_ADDRESS)) {
    558.  
    559.         ASSERT (NumberOfPagesSpanned != 0);
    560.  
    561. #if defined (_X86_)
    562.         RtlGetCallersAddress(&CallingAddress, &CallersCaller);
    563. #endif
    564.  
    565.         MiAddMdlTracker (MemoryDescriptorList,
    566.                          CallingAddress,
    567.                          CallersCaller,
    568.                          NumberOfPagesSpanned,
    569.                          1);
    570.     }
    571.  
    572.     return;
    573. }
    Просто ищи при каких условиях вызывается ExRaiseStatus
     
  3. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    Great, ну ты приколол...
    если ExRaiseStatus не будет вызван, это еще не означает, что не возникнет исключения доступа при обращении к странице
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Nouzui
    ну все равно в сорсе имхо можно найти те условия, при которых будут какие-либо исключения
     
  5. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    как и говорилось, спасет только просмотр каталога страниц.. свой код для x86, свой для x64.. про Альфы забыть
     
  6. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Нет.