📄 pgpmemlock.c
字号:
/*____________________________________________________________________________
Copyright (C) 1998 Network Associates, Inc.
All rights reserved.
PGPmemlock.c - PGPmemlock kernel mode device driver for locking memory
$Id: pgpMemLock.c,v 1.1 1999/04/09 19:14:49 pbj Exp $
____________________________________________________________________________*/
/*____________________________________________________________________________
This kernel mode device driver is used to lock memory pages into RAM
so that they will not get copied to the system page file. This
functionality is desired when allocating buffers that will contain
sensitive information (e.g. passwords) which could present a security
hazard if copied to the page file.
Usage :
1) memory allocation. Memory that is to be locked should be allocated
directly from the OS using the Win32 function VirtualAlloc :
PVOID pMem;
ULONG ulNumBytes;
ulNumBytes = number_of_bytes_to_allocate;
pMem = VirtualAlloc ( NULL, ulNumBytes, MEM_COMMIT, PAGE_READWRITE );
Notes:
NULL - the first parameter to VirtualAlloc must be NULL
ulNumBytes - the actual allocation is rounded up by VirtualAlloc
to the next page boundary
MEM_COMMIT - this flag causes a region of physical memory to be
committed for the allocated block of virtual memory
PAGE_READWRITE - this allows both read and write access to the memory
2) memory locking. Lock the memory by passing the address and size of
the allocated memory to the driver :
PGPMEMLOCKSTRUCT mls;
DWORD dw;
BOOL bDIOreturn;
mls.pMem = pMem;
mls.ulNumBytes = ulNumBytes;
bDIOreturn = DeviceIoControl( hPGPMemLockDriver,
IOCTL_PGPMEMLOCK_LOCK_MEMORY,
&mls,
sizeof( mls ),
&mls,
sizeof( mls ),
&dw,
NULL );
if ( !bDIOreturn )
{
// this is an error communicating with the driver
}
else
{
if ( mls.ulError != 0 )
{
// this is an error internal to the driver
}
else
{
// successfully locked!
}
}
3) unlocking the memory. To unlock the memory, the procedure is
similar :
PGPMEMLOCKSTRUCT mls;
DWORD dw;
BOOL bDIOreturn;
mls.pMem = pMem;
mls.ulNumBytes = ulNumBytes;
bDIOreturn = DeviceIoControl( hPGPMemLockDriver,
IOCTL_PGPMEMLOCK_UNLOCK_MEMORY,
&mls,
sizeof( mls ),
&mls,
sizeof( mls ),
&dw,
NULL );
if ( !bDIOreturn )
{
// this is an error communicating with the driver
}
else
{
if ( mls.ulError != 0 )
{
// this is an error internal to the driver
}
else
{
// successfully unlocked!
}
}
4) freeing the memory. Use VirtualFree to free the memory :
PVOID pMem;
VirtualFree( pMem, 0, MEM_RELEASE );
____________________________________________________________________________*/
#include "ntddk.h"
#include "stdarg.h"
#define PGP_WIN32 1
#include "pgpMemLockWin32.h"
// constants
// number of list items that can be held in internal heap
#define NUMITEMSPERBLOCK 64
// virtual memory paging in Win32 uses 4K byte pages (2^12)
#define WIN32PAGESIZE 12
// typedefs
// elements of list used to keep track of locked blocks
typedef struct _MEMLOCKITEM {
struct _MEMLOCKITEM* next;
PEPROCESS peProcess;
PFILE_OBJECT pfo;
ULONG ulPage;
ULONG ulNumPages;
PMDL pmdl;
} PGPMEMLOCKITEM, *PPGPMEMLOCKITEM;
// block of such items
typedef struct _MEMLOCKBLOCK {
struct _MEMLOCKBLOCK* nextBlock;
PGPMEMLOCKITEM item[NUMITEMSPERBLOCK];
} PGPMEMLOCKBLOCK, *PPGPMEMLOCKBLOCK;
// device object extension data structure
typedef struct _DEVEXTENSION {
KSPIN_LOCK slListLock;
PPGPMEMLOCKITEM pLockedList;
} DEVEXTENSION, *PDEVEXTENSION;
// macros
// DbgPrint prints a message to the kernel debugging console
#if DBG
#define PGPmlPrint(arg) DbgPrint arg
#else
#define PGPmlPrint(arg)
#endif
// globals
// pointer to local heap
static PPGPMEMLOCKBLOCK g_pHeapBlocks;
// pointer to head of free list
static PPGPMEMLOCKITEM g_pFreeHeapItems;
//----------------------------------------------------|
// internal item allocation routines
//
VOID
PGPmlHeapBlockInit (IN PPGPMEMLOCKBLOCK pmlb)
{
ULONG i = 0;
PPGPMEMLOCKITEM pmli = NULL;
pmlb->nextBlock = NULL;
pmli = &(pmlb->item[0]);
for (i=1; i<NUMITEMSPERBLOCK; i++)
{
pmli->next = &(pmlb->item[i]);
pmli = pmli->next;
}
pmli->next = NULL;
}
NTSTATUS
PGPmlHeapInit ()
{
ULONG i = 0;
PPGPMEMLOCKITEM pmli = NULL;
g_pHeapBlocks = ExAllocatePool (NonPagedPool,
sizeof(PGPMEMLOCKBLOCK));
if (g_pHeapBlocks)
{
PGPmlHeapBlockInit (g_pHeapBlocks);
g_pFreeHeapItems = &(g_pHeapBlocks->item[0]);
return STATUS_SUCCESS;
}
else return STATUS_NO_MEMORY;
}
NTSTATUS
PGPmlHeapDestroy ()
{
PPGPMEMLOCKBLOCK pmlb = NULL;
PPGPMEMLOCKBLOCK pmlbNext = NULL;
pmlb = g_pHeapBlocks;
while (pmlb)
{
pmlbNext = pmlb->nextBlock;
ExFreePool (pmlb);
pmlb = pmlbNext;
}
g_pFreeHeapItems = NULL;
return STATUS_SUCCESS;
}
PPGPMEMLOCKITEM
PGPmlAllocateItem ()
{
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKBLOCK pmlb = NULL;
PPGPMEMLOCKBLOCK pmlbNew = NULL;
ULONG i = 0;
// there is an item available
if (g_pFreeHeapItems)
{
// remove item from free list
pmli = g_pFreeHeapItems;
g_pFreeHeapItems = g_pFreeHeapItems->next;
return pmli;
}
// free list is empty, allocate more memory
pmlbNew = ExAllocatePool (NonPagedPool,
sizeof(PGPMEMLOCKBLOCK));
if (pmlbNew)
{
// append block to linked list of blocks
pmlb = g_pHeapBlocks;
while (pmlb->nextBlock) pmlb = pmlb->nextBlock;
pmlb->nextBlock = pmlbNew;
pmlbNew->nextBlock = NULL;
// link new items into a list
PGPmlHeapBlockInit (pmlbNew);
// first item will be returned to caller
pmli = &(pmlbNew->item[0]);
// add rest of new items to free list
g_pFreeHeapItems = &(pmlbNew->item[1]);
return pmli;
}
// couldn't get an item
return NULL;
}
VOID
PGPmlFreeItem (IN PPGPMEMLOCKITEM pmli)
{
// add item to list of free items
pmli->next = g_pFreeHeapItems;
g_pFreeHeapItems = pmli;
}
//----------------------------------------------------|
// wipe the specified memory block
//
// Arguments:
// ulPage - initial page being wiped
// ulNumPages - number of pages in block being wiped
//
VOID
PGPmlWipeBlock (
IN ULONG ulPage,
IN ULONG ulNumPages)
{
PVOID pmem;
ULONG ulBytes;
pmem = (PVOID)(ulPage << WIN32PAGESIZE);
ulBytes = ulNumPages << WIN32PAGESIZE;
memset (pmem, 0, ulBytes);
}
//----------------------------------------------------|
// add the specified memory block to list of blocks
//
// Arguments:
// pDevO - pointer to a device object
// ulPage - initial page being locked
// ulNumPages - number of pages in block being locked
// pmdl - pointer to MDL used to lock pages
//
NTSTATUS
PGPmlAddBlockToList (
IN PDEVICE_OBJECT pDevO,
IN PIRP pIrp,
IN ULONG ulPage,
IN ULONG ulNumPages,
IN PMDL pmdl)
{
PPGPMEMLOCKITEM pmli = NULL;
PDEVEXTENSION pde = NULL;
PEPROCESS peProcess = NULL;
PFILE_OBJECT pfo = NULL;
NTSTATUS ntStatus = STATUS_NO_MEMORY;
KIRQL irql;
peProcess = PsGetCurrentProcess ();
pfo = IoGetCurrentIrpStackLocation (pIrp)->FileObject;
pde = (PDEVEXTENSION)(pDevO->DeviceExtension);
KeAcquireSpinLock (&pde->slListLock, &irql);
// allocate new item
pmli = PGPmlAllocateItem ();
if (pmli)
{
// insert block information into item
pmli->peProcess = peProcess;
pmli->pfo = pfo;
pmli->ulPage = ulPage;
pmli->ulNumPages = ulNumPages;
pmli->pmdl = pmdl;
// insert item into list
pmli->next = pde->pLockedList;
pde->pLockedList = pmli;
ntStatus = STATUS_SUCCESS;
}
KeReleaseSpinLock (&pde->slListLock, irql);
return ntStatus;
}
//----------------------------------------------------|
// remove the specified memory block from list of
// locked blocks and unlock the memory
//
// Arguments:
// pDevO - pointer to a device object
// ulPage - initial page to unlock
// ulNumPages - number of pages in block to unlock
// bUnlock - TRUE=>unlock and remove from list
// FALSE=>remove from list only
//
NTSTATUS
PGPmlUnlockBlock (
IN PDEVICE_OBJECT pDevO,
IN PIRP pIrp,
IN ULONG ulPage,
IN ULONG ulNumPages,
IN ULONG bUnlock)
{
PDEVEXTENSION pde = NULL;
PMDL pmdl = NULL;
PEPROCESS peProcess = NULL;
PFILE_OBJECT pfo = NULL;
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKITEM pPrev = NULL;
NTSTATUS ntStatus = STATUS_NOT_LOCKED;
KIRQL irql;
peProcess = PsGetCurrentProcess ();
pfo = IoGetCurrentIrpStackLocation (pIrp)->FileObject;
pde = (PDEVEXTENSION)(pDevO->DeviceExtension);
KeAcquireSpinLock (&pde->slListLock, &irql);
// search list for specified block
pPrev = NULL;
pmli = pde->pLockedList;
while (pmli)
{
if ((pmli->peProcess == peProcess) &&
(pmli->pfo == pfo))
{
if ((pmli->ulPage == ulPage) &&
(pmli->ulNumPages == ulNumPages))
{
if (pPrev)
{
pPrev->next = pmli->next;
}
else
{
pde->pLockedList = pmli->next;
}
pmdl = pmli->pmdl;
PGPmlFreeItem (pmli);
ntStatus = STATUS_SUCCESS;
break;
}
}
pPrev = pmli;
pmli = pmli->next;
}
KeReleaseSpinLock (&pde->slListLock, irql);
// unlock pages and discard MDL
if (bUnlock && pmdl)
{
PGPmlWipeBlock (ulPage, ulNumPages);
MmUnlockPages(pmdl);
IoFreeMdl(pmdl);
}
return ntStatus;
}
//----------------------------------------------------|
// remove all of this handle's memory blocks from
// list of blocks and unlock the memory
//
// Arguments:
// pDevO - pointer to a device object
//
VOID
PGPmlUnlockHandleBlocks (
IN PDEVICE_OBJECT pDevO,
IN PIRP pIrp)
{
PDEVEXTENSION pde = NULL;
PEPROCESS peProcess = NULL;
PFILE_OBJECT pfo = NULL;
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKITEM pPrev = NULL;
PPGPMEMLOCKITEM pNext = NULL;
KIRQL irql;
peProcess = PsGetCurrentProcess ();
pfo = IoGetCurrentIrpStackLocation (pIrp)->FileObject;
pde = (PDEVEXTENSION)(pDevO->DeviceExtension);
// first wipe any blocks belonging to this handle
pmli = pde->pLockedList;
while (pmli)
{
if ((pmli->peProcess == peProcess) &&
(pmli->pfo == pfo))
{
PGPmlWipeBlock (pmli->ulPage, pmli->ulNumPages);
}
pmli = pmli->next;
}
KeAcquireSpinLock (&pde->slListLock, &irql);
// search list for block belonging to this handle
pPrev = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -