mirror of
https://github.com/reactos/reactos.git
synced 2024-10-07 18:04:41 +00:00
[NTOS]: Add some paranoid-invariant list access checks to the pool code. They serve a dual purpose: catch pool corruption by broken drivers/kernel code, as well as catch malicious modification of the pool links as part of a kernel-mode exploit.
[NTOS]: Not yet used, thanks to Arthur for the idea. See comment for more information. svn path=/trunk/; revision=47596
This commit is contained in:
parent
81589f83ca
commit
745031cf0b
|
@ -35,6 +35,123 @@ PKGUARDED_MUTEX ExpPagedPoolMutex;
|
||||||
#define POOL_NEXT_BLOCK(x) POOL_BLOCK((x), (x)->BlockSize)
|
#define POOL_NEXT_BLOCK(x) POOL_BLOCK((x), (x)->BlockSize)
|
||||||
#define POOL_PREV_BLOCK(x) POOL_BLOCK((x), -(x)->PreviousSize)
|
#define POOL_PREV_BLOCK(x) POOL_BLOCK((x), -(x)->PreviousSize)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pool list access debug macros, similar to Arthur's pfnlist.c work.
|
||||||
|
* Microsoft actually implements similar checks in the Windows Server 2003 SP1
|
||||||
|
* pool code, but only for checked builds.
|
||||||
|
* As of Vista, however, an MSDN Blog entry by a Security Team Manager indicates
|
||||||
|
* that these checks are done even on retail builds, due to the increasing
|
||||||
|
* number of kernel-mode attacks which depend on dangling list pointers and other
|
||||||
|
* kinds of list-based attacks.
|
||||||
|
* For now, I will leave these checks on all the time, but later they are likely
|
||||||
|
* to be DBG-only, at least until there are enough kernel-mode security attacks
|
||||||
|
* against ReactOS to warrant the performance hit.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
FORCEINLINE
|
||||||
|
PLIST_ENTRY
|
||||||
|
ExpDecodePoolLink(IN PLIST_ENTRY Link)
|
||||||
|
{
|
||||||
|
return (PLIST_ENTRY)((ULONG_PTR)Link & ~1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PLIST_ENTRY
|
||||||
|
ExpEncodePoolLink(IN PLIST_ENTRY Link)
|
||||||
|
{
|
||||||
|
return (PLIST_ENTRY)((ULONG_PTR)Link | 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
ExpCheckPoolLinks(IN PLIST_ENTRY ListHead)
|
||||||
|
{
|
||||||
|
if ((ExpDecodePoolLink(ExpDecodePoolLink(ListHead->Flink)->Blink) != ListHead) ||
|
||||||
|
(ExpDecodePoolLink(ExpDecodePoolLink(ListHead->Blink)->Flink) != ListHead))
|
||||||
|
{
|
||||||
|
KeBugCheckEx(BAD_POOL_HEADER,
|
||||||
|
3,
|
||||||
|
(ULONG_PTR)ListHead,
|
||||||
|
(ULONG_PTR)ExpDecodePoolLink(ExpDecodePoolLink(ListHead->Flink)->Blink),
|
||||||
|
(ULONG_PTR)ExpDecodePoolLink(ExpDecodePoolLink(ListHead->Blink)->Flink));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
ExpInitializePoolListHead(IN PLIST_ENTRY ListHead)
|
||||||
|
{
|
||||||
|
ListHead->Flink = ListHead->Blink = ExpEncodePoolLink(ListHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
BOOLEAN
|
||||||
|
ExpIsPoolListEmpty(IN PLIST_ENTRY ListHead)
|
||||||
|
{
|
||||||
|
return (ExpDecodePoolLink(ListHead->Flink) == ListHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
ExpRemovePoolEntryList(IN PLIST_ENTRY Entry)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Blink, Flink;
|
||||||
|
Flink = ExpDecodePoolLink(Entry->Flink);
|
||||||
|
Blink = ExpDecodePoolLink(Entry->Blink);
|
||||||
|
Blink->Flink = ExpEncodePoolLink(Flink);
|
||||||
|
Flink->Blink = ExpEncodePoolLink(Blink);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PLIST_ENTRY
|
||||||
|
ExpRemovePoolHeadList(IN PLIST_ENTRY ListHead)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Head;
|
||||||
|
Head = ExpDecodePoolLink(ListHead->Flink);
|
||||||
|
ExpRemovePoolEntryList(Head);
|
||||||
|
return Head;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
PLIST_ENTRY
|
||||||
|
ExpRemovePoolTailList(IN PLIST_ENTRY ListHead)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Tail;
|
||||||
|
Tail = ExpDecodePoolLink(ListHead->Blink);
|
||||||
|
ExpRemovePoolEntryList(Tail);
|
||||||
|
return Tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
ExpInsertPoolTailList(IN PLIST_ENTRY ListHead,
|
||||||
|
IN PLIST_ENTRY Entry)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Blink;
|
||||||
|
ExpCheckPoolLinks(ListHead);
|
||||||
|
Blink = ExpDecodePoolLink(ListHead->Blink);
|
||||||
|
Entry->Flink = ExpEncodePoolLink(ListHead);
|
||||||
|
Entry->Blink = ExpEncodePoolLink(Blink);
|
||||||
|
Blink->Flink = ExpEncodePoolLink(Entry);
|
||||||
|
ListHead->Blink = ExpEncodePoolLink(Entry);
|
||||||
|
ExpCheckPoolLinks(ListHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
ExpInsertPoolHeadList(IN PLIST_ENTRY ListHead,
|
||||||
|
IN PLIST_ENTRY Entry)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Flink;
|
||||||
|
ExpCheckPoolLinks(ListHead);
|
||||||
|
Flink = ExpDecodePoolLink(ListHead->Blink);
|
||||||
|
Entry->Flink = ExpEncodePoolLink(Flink);
|
||||||
|
Entry->Blink = ExpEncodePoolLink(ListHead);
|
||||||
|
Flink->Blink = ExpEncodePoolLink(Entry);
|
||||||
|
ListHead->Flink = ExpEncodePoolLink(Entry);
|
||||||
|
ExpCheckPoolLinks(ListHead);
|
||||||
|
}
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
Loading…
Reference in a new issue