Author: sir_richard Date: Sat Jun 5 20:02:45 2010 New Revision: 47596
URL: http://svn.reactos.org/svn/reactos?rev=47596&view=rev Log: [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.
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/expool.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] Sat Jun 5 20:02:45 2010 @@ -34,7 +34,124 @@ #define POOL_BLOCK(x, i) (PPOOL_HEADER)((ULONG_PTR)(x) + ((i) * POOL_BLOCK_SIZE)) #define POOL_NEXT_BLOCK(x) POOL_BLOCK((x), (x)->BlockSize) #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 **********************************************************/
VOID