X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FMem%2FHeapGuard.c;h=fd6aeee8da9d70c5e7523d41064cdc2b85e5c6df;hp=ac043b5d9b264b2c3e27cff8727d1824d52aa304;hb=36f2f049a83d82f7c0c847202c9ce2974492c1ab;hpb=dd12683e1f82a8d17fb6167ce4b3f6f3a1d10559 diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c index ac043b5d9b..fd6aeee8da 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c @@ -70,7 +70,7 @@ SetBits ( StartBit = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address); EndBit = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS; - if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) { + if ((StartBit + BitNumber) >= GUARDED_HEAP_MAP_ENTRY_BITS) { Msbs = (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) % GUARDED_HEAP_MAP_ENTRY_BITS; Lsbs = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS; @@ -123,7 +123,7 @@ ClearBits ( StartBit = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address); EndBit = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS; - if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) { + if ((StartBit + BitNumber) >= GUARDED_HEAP_MAP_ENTRY_BITS) { Msbs = (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) % GUARDED_HEAP_MAP_ENTRY_BITS; Lsbs = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS; @@ -188,10 +188,14 @@ GetBits ( Lsbs = 0; } - Result = RShiftU64 ((*BitMap), StartBit) & (LShiftU64 (1, Msbs) - 1); - if (Lsbs > 0) { - BitMap += 1; - Result |= LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msbs); + if (StartBit == 0 && BitNumber == GUARDED_HEAP_MAP_ENTRY_BITS) { + Result = *BitMap; + } else { + Result = RShiftU64((*BitMap), StartBit) & (LShiftU64(1, Msbs) - 1); + if (Lsbs > 0) { + BitMap += 1; + Result |= LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msbs); + } } return Result; @@ -576,6 +580,10 @@ SetGuardPage ( IN EFI_PHYSICAL_ADDRESS BaseAddress ) { + if (gCpu == NULL) { + return; + } + // // Set flag to make sure allocating memory without GUARD for page table // operation; otherwise infinite loops could be caused. @@ -606,6 +614,10 @@ UnsetGuardPage ( { UINT64 Attributes; + if (gCpu == NULL) { + return; + } + // // Once the Guard page is unset, it will be freed back to memory pool. NX // memory protection must be restored for this page if NX is enabled for free @@ -652,7 +664,7 @@ IsMemoryTypeToGuard ( UINT64 ConfigBit; BOOLEAN InSmm; - if (gCpu == NULL || AllocateType == AllocateAddress) { + if (AllocateType == AllocateAddress) { return FALSE; } @@ -1164,6 +1176,128 @@ CoreConvertPagesWithGuard ( return CoreConvertPages (Start, NumberOfPages, NewType); } +/** + Set all Guard pages which cannot be set before CPU Arch Protocol installed. +**/ +VOID +SetAllGuardPages ( + VOID + ) +{ + UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 TableEntry; + UINT64 Address; + UINT64 GuardPage; + INTN Level; + UINTN Index; + BOOLEAN OnGuarding; + + if (mGuardedMemoryMap == 0 || + mMapLevel == 0 || + mMapLevel > GUARDED_HEAP_MAP_TABLE_DEPTH) { + return; + } + + CopyMem (Entries, mLevelMask, sizeof (Entries)); + CopyMem (Shifts, mLevelShift, sizeof (Shifts)); + + SetMem (Tables, sizeof(Tables), 0); + SetMem (Addresses, sizeof(Addresses), 0); + SetMem (Indices, sizeof(Indices), 0); + + Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel; + Tables[Level] = mGuardedMemoryMap; + Address = 0; + OnGuarding = FALSE; + + DEBUG_CODE ( + DumpGuardedMemoryBitmap (); + ); + + while (TRUE) { + if (Indices[Level] > Entries[Level]) { + Tables[Level] = 0; + Level -= 1; + } else { + + TableEntry = ((UINT64 *)(UINTN)(Tables[Level]))[Indices[Level]]; + Address = Addresses[Level]; + + if (TableEntry == 0) { + + OnGuarding = FALSE; + + } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { + + Level += 1; + Tables[Level] = TableEntry; + Addresses[Level] = Address; + Indices[Level] = 0; + + continue; + + } else { + + Index = 0; + while (Index < GUARDED_HEAP_MAP_ENTRY_BITS) { + if ((TableEntry & 1) == 1) { + if (OnGuarding) { + GuardPage = 0; + } else { + GuardPage = Address - EFI_PAGE_SIZE; + } + OnGuarding = TRUE; + } else { + if (OnGuarding) { + GuardPage = Address; + } else { + GuardPage = 0; + } + OnGuarding = FALSE; + } + + if (GuardPage != 0) { + SetGuardPage (GuardPage); + } + + if (TableEntry == 0) { + break; + } + + TableEntry = RShiftU64 (TableEntry, 1); + Address += EFI_PAGE_SIZE; + Index += 1; + } + } + } + + if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) { + break; + } + + Indices[Level] += 1; + Address = (Level == 0) ? 0 : Addresses[Level - 1]; + Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]); + + } +} + +/** + Notify function used to set all Guard pages before CPU Arch Protocol installed. +**/ +VOID +HeapGuardCpuArchProtocolNotify ( + VOID + ) +{ + ASSERT (gCpu != NULL); + SetAllGuardPages (); +} + /** Helper function to convert a UINT64 value in binary to a string.