This solution is equivalent to DXE core.
AllocatePool() allocates POOL_TAIL after the buffer.
This POOL_TAIL is checked at FreePool().
If the there is buffer overflow, the issue can be caught at FreePool().
This patch could also handle the eight-byte aligned allocation
requirement. The discussion related to the eight-byte aligned
allocation requirement is at
https://lists.01.org/pipermail/edk2-devel/2017-April/009995.html.
According to the PI spec (Vol 4, Section 3.2 SmmAllocatePool()):
The SmmAllocatePool() function ... All allocations are eight-byte aligned.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
//\r
#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)\r
\r
//\r
#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)\r
\r
+#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')\r
+\r
- UINTN Size;\r
- BOOLEAN Available;\r
- EFI_MEMORY_TYPE Type;\r
+ UINT32 Signature;\r
+ BOOLEAN Available;\r
+ EFI_MEMORY_TYPE Type;\r
+ UINTN Size;\r
+#define POOL_TAIL_SIGNATURE SIGNATURE_32('p','t','a','l')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ UINT32 Reserved;\r
+ UINTN Size;\r
+} POOL_TAIL;\r
+\r
+#define POOL_OVERHEAD (sizeof(POOL_HEADER) + sizeof(POOL_TAIL))\r
+\r
+#define HEAD_TO_TAIL(a) \\r
+ ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL)));\r
+\r
typedef struct {\r
POOL_HEADER Header;\r
LIST_ENTRY Link;\r
typedef struct {\r
POOL_HEADER Header;\r
LIST_ENTRY Link;\r
{\r
EFI_STATUS Status;\r
FREE_POOL_HEADER *Hdr;\r
{\r
EFI_STATUS Status;\r
FREE_POOL_HEADER *Hdr;\r
EFI_PHYSICAL_ADDRESS Address;\r
SMM_POOL_TYPE SmmPoolType;\r
\r
EFI_PHYSICAL_ADDRESS Address;\r
SMM_POOL_TYPE SmmPoolType;\r
\r
} else {\r
Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);\r
if (!EFI_ERROR (Status)) {\r
} else {\r
Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);\r
if (!EFI_ERROR (Status)) {\r
+ Hdr->Header.Signature = 0;\r
Hdr->Header.Size >>= 1;\r
Hdr->Header.Available = TRUE;\r
Hdr->Header.Size >>= 1;\r
Hdr->Header.Available = TRUE;\r
- Hdr->Header.Type = PoolType;\r
+ Hdr->Header.Type = 0;\r
+ Tail = HEAD_TO_TAIL(&Hdr->Header);\r
+ Tail->Signature = 0;\r
+ Tail->Size = 0;\r
InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);\r
Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);\r
}\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);\r
Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);\r
}\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
+ Hdr->Header.Signature = POOL_HEAD_SIGNATURE;\r
Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;\r
Hdr->Header.Available = FALSE;\r
Hdr->Header.Type = PoolType;\r
Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;\r
Hdr->Header.Available = FALSE;\r
Hdr->Header.Type = PoolType;\r
+ Tail = HEAD_TO_TAIL(&Hdr->Header);\r
+ Tail->Signature = POOL_TAIL_SIGNATURE;\r
+ Tail->Size = Hdr->Header.Size;\r
}\r
\r
*FreePoolHdr = Hdr;\r
}\r
\r
*FreePoolHdr = Hdr;\r
{\r
UINTN PoolIndex;\r
SMM_POOL_TYPE SmmPoolType;\r
{\r
UINTN PoolIndex;\r
SMM_POOL_TYPE SmmPoolType;\r
\r
ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);\r
ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);\r
\r
ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);\r
ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);\r
SmmPoolType = UefiMemoryTypeToSmmPoolType(FreePoolHdr->Header.Type);\r
\r
PoolIndex = (UINTN) (HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);\r
SmmPoolType = UefiMemoryTypeToSmmPoolType(FreePoolHdr->Header.Type);\r
\r
PoolIndex = (UINTN) (HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);\r
+ FreePoolHdr->Header.Signature = 0;\r
FreePoolHdr->Header.Available = TRUE;\r
FreePoolHdr->Header.Available = TRUE;\r
+ FreePoolHdr->Header.Type = 0;\r
+ PoolTail = HEAD_TO_TAIL(&FreePoolHdr->Header);\r
+ PoolTail->Signature = 0;\r
+ PoolTail->Size = 0;\r
ASSERT (PoolIndex < MAX_POOL_INDEX);\r
InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &FreePoolHdr->Link);\r
return EFI_SUCCESS;\r
ASSERT (PoolIndex < MAX_POOL_INDEX);\r
InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &FreePoolHdr->Link);\r
return EFI_SUCCESS;\r
)\r
{\r
POOL_HEADER *PoolHdr;\r
)\r
{\r
POOL_HEADER *PoolHdr;\r
FREE_POOL_HEADER *FreePoolHdr;\r
EFI_STATUS Status;\r
EFI_PHYSICAL_ADDRESS Address;\r
FREE_POOL_HEADER *FreePoolHdr;\r
EFI_STATUS Status;\r
EFI_PHYSICAL_ADDRESS Address;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Size += sizeof (*PoolHdr);\r
+ //\r
+ // Adjust the size by the pool header & tail overhead\r
+ //\r
+ Size += POOL_OVERHEAD;\r
if (Size > MAX_POOL_SIZE) {\r
Size = EFI_SIZE_TO_PAGES (Size);\r
Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
if (Size > MAX_POOL_SIZE) {\r
Size = EFI_SIZE_TO_PAGES (Size);\r
Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
}\r
\r
PoolHdr = (POOL_HEADER*)(UINTN)Address;\r
}\r
\r
PoolHdr = (POOL_HEADER*)(UINTN)Address;\r
+ PoolHdr->Signature = POOL_HEAD_SIGNATURE;\r
PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);\r
PoolHdr->Available = FALSE;\r
PoolHdr->Type = PoolType;\r
PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);\r
PoolHdr->Available = FALSE;\r
PoolHdr->Type = PoolType;\r
+ PoolTail = HEAD_TO_TAIL(PoolHdr);\r
+ PoolTail->Signature = POOL_TAIL_SIGNATURE;\r
+ PoolTail->Size = PoolHdr->Size;\r
*Buffer = PoolHdr + 1;\r
return Status;\r
}\r
*Buffer = PoolHdr + 1;\r
return Status;\r
}\r
)\r
{\r
FREE_POOL_HEADER *FreePoolHdr;\r
)\r
{\r
FREE_POOL_HEADER *FreePoolHdr;\r
\r
if (Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);\r
\r
if (Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);\r
+ ASSERT (FreePoolHdr->Header.Signature == POOL_HEAD_SIGNATURE);\r
ASSERT (!FreePoolHdr->Header.Available);\r
ASSERT (!FreePoolHdr->Header.Available);\r
+ PoolTail = HEAD_TO_TAIL(&FreePoolHdr->Header);\r
+ ASSERT (PoolTail->Signature == POOL_TAIL_SIGNATURE);\r
+ ASSERT (FreePoolHdr->Header.Size == PoolTail->Size);\r
+\r
+ if (FreePoolHdr->Header.Signature != POOL_HEAD_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (PoolTail->Signature != POOL_TAIL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (FreePoolHdr->Header.Size != PoolTail->Size) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {\r
ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);\r
\r
if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {\r
ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);\r