public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Laszlo Ersek" <lersek@redhat.com>
To: devel@edk2.groups.io
Cc: Dun Tan <dun.tan@intel.com>, Gerd Hoffmann <kraxel@redhat.com>,
	Rahul Kumar <rahul1.kumar@intel.com>, Ray Ni <ray.ni@intel.com>
Subject: [edk2-devel] [edk2-stable202402 PATCH 1/2] UefiCpuPkg/PiSmmCpuDxeSmm: distinguish GetSmBase() failure modes
Date: Tue, 13 Feb 2024 22:09:17 +0100	[thread overview]
Message-ID: <20240213210918.16372-2-lersek@redhat.com> (raw)
In-Reply-To: <20240213210918.16372-1-lersek@redhat.com>

Commit 725acd0b9cc0 ("UefiCpuPkg: Avoid assuming only one smmbasehob",
2023-12-12) introduced a helper function called GetSmBase(), replacing the
lookup of the first and only "gSmmBaseHobGuid" GUID HOB, with iterated
lookups plus memory allocation.

This introduced a new failure mode for setting "mCpuHotPlugData.SmBase".
Namely, before commit 725acd0b9cc0, "mCpuHotPlugData.SmBase" would be set
to NULL if and only if the GUID HOB was absent. After the commit, a NULL
assignment would be possible if the GUID HOB was absent, *or* one of the
memory allocations inside GetSmBase() failed.

In relation to this conflation of distinct failure modes, commit
725acd0b9cc0 actually introduced a NULL pointer dereference. Namely, a
NULL "mCpuHotPlugData.SmBase" is not handled properly at all now. We're
going to fix that NULL pointer dereference in a subsequent patch; however,
as a pre-requisite for that we need to tell apart the failure modes of
GetSmBase().

For memory allocation failures, return EFI_OUT_OF_RESOURCES. Move the
"assertion" that SMRAM cannot be exhausted happen out to the caller
(PiCpuSmmEntry()). Strengthen the assertion by adding an explicit
CpuDeadLoop() call. (Note: GetSmBase() *already* calls CpuDeadLoop() if
(NumberOfProcessors != MaxNumberOfCpus).)

For the absence of the GUID HOB, return EFI_NOT_FOUND.

For good measure, make GetSmBase() STATIC (it should have been STATIC from
the start).

This is just a refactoring, no behavioral difference is intended (beyond
the explicit CpuDeadLoop() upon SMRAM exhaustion).

Cc: Dun Tan <dun.tan@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=4682
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---

Notes:
    context:-U4

 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 40 ++++++++++++++------
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
index cd394826ffcf..09382945ddb4 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -619,16 +619,23 @@ SmBaseHobCompare (
 
 /**
   Extract SmBase for all CPU from SmmBase HOB.
 
-  @param[in]  MaxNumberOfCpus   Max NumberOfCpus.
+  @param[in]  MaxNumberOfCpus        Max NumberOfCpus.
 
-  @retval SmBaseBuffer          Pointer to SmBase Buffer.
-  @retval NULL                  gSmmBaseHobGuid was not been created.
+  @param[out] AllocatedSmBaseBuffer  Pointer to SmBase Buffer allocated
+                                     by this function. Only set if the
+                                     function returns EFI_SUCCESS.
+
+  @retval EFI_SUCCESS           SmBase Buffer output successfully.
+  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+  @retval EFI_NOT_FOUND         gSmmBaseHobGuid was never created.
 **/
-UINTN *
+STATIC
+EFI_STATUS
 GetSmBase (
-  IN  UINTN  MaxNumberOfCpus
+  IN  UINTN  MaxNumberOfCpus,
+  OUT UINTN  **AllocatedSmBaseBuffer
   )
 {
   UINTN              HobCount;
   EFI_HOB_GUID_TYPE  *GuidHob;
@@ -649,9 +656,9 @@ GetSmBase (
   NumberOfProcessors = 0;
 
   FirstSmmBaseGuidHob = GetFirstGuidHob (&gSmmBaseHobGuid);
   if (FirstSmmBaseGuidHob == NULL) {
-    return NULL;
+    return EFI_NOT_FOUND;
   }
 
   GuidHob = FirstSmmBaseGuidHob;
   while (GuidHob != NULL) {
@@ -671,11 +678,10 @@ GetSmBase (
     CpuDeadLoop ();
   }
 
   SmBaseHobs = AllocatePool (sizeof (SMM_BASE_HOB_DATA *) * HobCount);
-  ASSERT (SmBaseHobs != NULL);
   if (SmBaseHobs == NULL) {
-    return NULL;
+    return EFI_OUT_OF_RESOURCES;
   }
 
   //
   // Record each SmmBaseHob pointer in the SmBaseHobs.
@@ -691,9 +697,9 @@ GetSmBase (
   SmBaseBuffer = (UINTN *)AllocatePool (sizeof (UINTN) * (MaxNumberOfCpus));
   ASSERT (SmBaseBuffer != NULL);
   if (SmBaseBuffer == NULL) {
     FreePool (SmBaseHobs);
-    return NULL;
+    return EFI_OUT_OF_RESOURCES;
   }
 
   QuickSort (SmBaseHobs, HobCount, sizeof (SMM_BASE_HOB_DATA *), (BASE_SORT_COMPARE)SmBaseHobCompare, &SortBuffer);
   PrevProcessorIndex = 0;
@@ -713,9 +719,10 @@ GetSmBase (
     PrevProcessorIndex += SmBaseHobs[HobIndex]->NumberOfProcessors;
   }
 
   FreePool (SmBaseHobs);
-  return SmBaseBuffer;
+  *AllocatedSmBaseBuffer = SmBaseBuffer;
+  return EFI_SUCCESS;
 }
 
 /**
   Function to compare 2 MP_INFORMATION2_HOB_DATA pointer based on ProcessorIndex.
@@ -1110,10 +1117,17 @@ PiCpuSmmEntry (
   //
   // Retrive the allocated SmmBase from gSmmBaseHobGuid. If found,
   // means the SmBase relocation has been done.
   //
-  mCpuHotPlugData.SmBase = GetSmBase (mMaxNumberOfCpus);
-  if (mCpuHotPlugData.SmBase != NULL) {
+  mCpuHotPlugData.SmBase = NULL;
+  Status                 = GetSmBase (mMaxNumberOfCpus, &mCpuHotPlugData.SmBase);
+  if (Status == EFI_OUT_OF_RESOURCES) {
+    ASSERT (Status != EFI_OUT_OF_RESOURCES);
+    CpuDeadLoop ();
+  }
+
+  if (!EFI_ERROR (Status)) {
+    ASSERT (mCpuHotPlugData.SmBase != NULL);
     //
     // Check whether the Required TileSize is enough.
     //
     if (TileSize > SIZE_8KB) {
@@ -1125,8 +1139,10 @@ PiCpuSmmEntry (
     }
 
     mSmmRelocated = TRUE;
   } else {
+    ASSERT (Status == EFI_NOT_FOUND);
+    ASSERT (mCpuHotPlugData.SmBase == NULL);
     //
     // When the HOB doesn't exist, allocate new SMBASE itself.
     //
     DEBUG ((DEBUG_INFO, "PiCpuSmmEntry: gSmmBaseHobGuid not found!\n"));



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#115417): https://edk2.groups.io/g/devel/message/115417
Mute This Topic: https://groups.io/mt/104341342/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2024-02-13 21:09 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-13 21:09 [edk2-devel] [edk2-stable202402 PATCH 0/2] UefiCpuPkg/PiSmmCpuDxeSmm: fix NULL deref when gSmmBaseHobGuid is missing Laszlo Ersek
2024-02-13 21:09 ` Laszlo Ersek [this message]
2024-02-13 21:35   ` [edk2-devel] [edk2-stable202402 PATCH 1/2] UefiCpuPkg/PiSmmCpuDxeSmm: distinguish GetSmBase() failure modes Laszlo Ersek
2024-02-14  3:43     ` Michael D Kinney
2024-02-14 11:22       ` Laszlo Ersek
2024-02-14 13:08       ` Leif Lindholm
2024-02-14 17:26         ` Michael D Kinney
2024-02-15  8:44           ` Laszlo Ersek
2024-02-19  9:12             ` duntan
2024-02-13 21:09 ` [edk2-devel] [edk2-stable202402 PATCH 2/2] UefiCpuPkg/PiSmmCpuDxeSmm: fix NULL deref when gSmmBaseHobGuid is missing Laszlo Ersek
2024-02-14  9:01 ` [edk2-devel] [edk2-stable202402 PATCH 0/2] " Gerd Hoffmann
2024-02-14  9:40   ` rahul.r.kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240213210918.16372-2-lersek@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox