NT4/private/ntos/mm/i386/probewrt.c
2020-09-30 17:12:29 +02:00

139 lines
3.2 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
probewrt.c
Abstract:
This module contains the routine to support probe for write on
the Intel 386. The Intel 386 has the unique property that in
kernel mode the writable bit of the PTE is ignored. This allows
the kernel to write user mode pages which may be read only. Note,
that copy-on-write pages are protected as read-only as well, hence
the kernel could write to a user-mode copy on write page and the
copy on write would not occur.
Author:
Lou Perazzoli (loup) 6-Apr-1990
Environment:
Kernel mode only. Non-paged.
Revision History:
--*/
#include "mi.h"
VOID
MmProbeForWrite (
IN PVOID Address,
IN ULONG Length
)
/*++
Routine Description:
This function probes an address for write accessibility on
the Intel 386.
Arguments:
Address - Supplies a pointer to the structure to probe.
Length - Supplies the length of the structure.
Return Value:
None. If the Address cannot be written an exception is raised.
--*/
{
PMMPTE PointerPte;
PMMPTE LastPte;
MMPTE PteContents;
CCHAR Temp;
//
// Loop on the copy on write case until the page is only
// writable.
//
if (Address >= (PVOID)MM_HIGHEST_USER_ADDRESS) {
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
}
PointerPte = MiGetPteAddress (Address);
LastPte = MiGetPteAddress ((PVOID)((ULONG)Address + Length - 1));
while (PointerPte <= LastPte) {
for (;;) {
//
// Touch the address as a byte to check for readability and
// get the PTE built.
//
do {
Temp = *(volatile CCHAR *)Address;
PteContents = *(volatile MMPTE *)PointerPte;
} while (PteContents.u.Hard.Valid == 0);
if (PteContents.u.Hard.Write == 1) {
//
// The PTE is writable and not copy on write.
//
break;
}
if (PteContents.u.Hard.CopyOnWrite == 1) {
//
// The PTE is copy on write. Call the pager and let
// it deal with this. Once the page fault is complete,
// this loop will again be repeated and the PTE will
// again be checked for write access and copy-on-write
// access. The PTE could still be copy-on-write even
// after the pager is called if the page table page
// was removed from the working set at this time (unlikely,
// but still possible).
//
if (!NT_SUCCESS (MmAccessFault (TRUE,
Address,
UserMode))) {
//
// Raise an access violation status.
//
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
}
} else {
//
// Raise an access violation status.
//
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
}
}
PointerPte += 1;
Address = (PVOID)((ULONG)Address + PAGE_SIZE);
}
}