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

probewrt.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 probewrt.c 00008 00009 Abstract: 00010 00011 This module contains the routine to support probe for write on 00012 the Intel 386. The Intel 386 has the unique property that in 00013 kernel mode the writable bit of the PTE is ignored. This allows 00014 the kernel to write user mode pages which may be read only. Note, 00015 that copy-on-write pages are protected as read-only as well, hence 00016 the kernel could write to a user-mode copy on write page and the 00017 copy on write would not occur. 00018 00019 00020 Author: 00021 00022 Lou Perazzoli (loup) 6-Apr-1990 00023 00024 Environment: 00025 00026 Kernel mode only. Non-paged. 00027 00028 Revision History: 00029 00030 --*/ 00031 00032 #include "mi.h" 00033 00034 00035 VOID 00036 MmProbeForWrite ( 00037 IN PVOID Address, 00038 IN ULONG Length 00039 ) 00040 00041 /*++ 00042 00043 Routine Description: 00044 00045 This function probes an address for write accessibility on 00046 the Intel 386. 00047 00048 Arguments: 00049 00050 Address - Supplies a pointer to the structure to probe. 00051 00052 Length - Supplies the length of the structure. 00053 00054 Return Value: 00055 00056 None. If the Address cannot be written an exception is raised. 00057 00058 --*/ 00059 00060 { 00061 PMMPTE PointerPte; 00062 PMMPTE LastPte; 00063 MMPTE PteContents; 00064 CCHAR Temp; 00065 00066 // 00067 // Loop on the copy on write case until the page is only 00068 // writable. 00069 // 00070 00071 if (Address >= (PVOID)MM_HIGHEST_USER_ADDRESS) { 00072 ExRaiseStatus(STATUS_ACCESS_VIOLATION); 00073 } 00074 00075 PointerPte = MiGetPteAddress (Address); 00076 LastPte = MiGetPteAddress ((PVOID)((ULONG)Address + Length - 1)); 00077 00078 while (PointerPte <= LastPte) { 00079 00080 for (;;) { 00081 00082 // 00083 // Touch the address as a byte to check for readability and 00084 // get the PTE built. 00085 // 00086 00087 do { 00088 Temp = *(volatile CCHAR *)Address; 00089 PteContents = *(volatile MMPTE *)PointerPte; 00090 } while (PteContents.u.Hard.Valid == 0); 00091 00092 if (PteContents.u.Hard.Write == 1) { 00093 00094 // 00095 // The PTE is writable and not copy on write. 00096 // 00097 00098 break; 00099 } 00100 00101 if (PteContents.u.Hard.CopyOnWrite == 1) { 00102 00103 // 00104 // The PTE is copy on write. Call the pager and let 00105 // it deal with this. Once the page fault is complete, 00106 // this loop will again be repeated and the PTE will 00107 // again be checked for write access and copy-on-write 00108 // access. The PTE could still be copy-on-write even 00109 // after the pager is called if the page table page 00110 // was removed from the working set at this time (unlikely, 00111 // but still possible). 00112 // 00113 00114 if (!NT_SUCCESS (MmAccessFault (TRUE, 00115 Address, 00116 UserMode))) { 00117 00118 // 00119 // Raise an access violation status. 00120 // 00121 00122 ExRaiseStatus(STATUS_ACCESS_VIOLATION); 00123 00124 } 00125 } else { 00126 00127 // 00128 // Raise an access violation status. 00129 // 00130 00131 ExRaiseStatus(STATUS_ACCESS_VIOLATION); 00132 00133 } 00134 } 00135 PointerPte += 1; 00136 Address = (PVOID)((ULONG)Address + PAGE_SIZE); 00137 } 00138 }

Generated on Sat May 15 19:41:26 2004 for test by doxygen 1.3.7