[edk2] [RFC v5 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Validate memory address ranges

Paulo Alcantara posted 8 patches 6 years, 11 months ago
[edk2] [RFC v5 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Validate memory address ranges
Posted by Paulo Alcantara 6 years, 11 months ago
Introduce a new IsLinearAddressRangeValid() function to validate a given
address range and check whether or not it is valid.

This function is useful for validating ranges of memory addresses during
stack traces in X64.

Contributed-under: TianoCore Contribution Agreement 1.1
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Requested-by: Brian Johnson <brian.johnson@hpe.com>
Signed-off-by: Paulo Alcantara <paulo@paulo.ac>
---
 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c       | 40 ++++++++++++++++++++
 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h       | 18 +++++++++
 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 40 ++++++++++++--------
 3 files changed, 83 insertions(+), 15 deletions(-)

diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
index 7ac13640de..e1dd054259 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
@@ -589,3 +589,43 @@ IsLinearAddressValid (
 
   return AddressValid;
 }
+
+/**
+  Check if a linear address range is valid.
+
+  @param[in]  Cr0                 CR0 control register.
+  @param[in]  Cr3                 CR3 control register.
+  @param[in]  Cr4                 CR4 control register.
+  @param[in]  LinearAddressStart  Linear address start.
+  @param[in]  LinearAddressEnd    Linear address end.
+**/
+BOOLEAN
+IsLinearAddressRangeValid (
+  IN  UINTN              Cr0,
+  IN  UINTN              Cr3,
+  IN  UINTN              Cr4,
+  IN  UINTN              LinearAddressStart,
+  IN  UINTN              LinearAddressEnd
+  )
+{
+  //
+  // Check for valid input parameters
+  //
+  if (LinearAddressStart == 0 || LinearAddressEnd == 0 ||
+      LinearAddressStart > LinearAddressEnd) {
+    return FALSE;
+  }
+
+  //
+  // Validate all linear addresses within the given range
+  //
+  for (LinearAddressStart &= ~(SIZE_4KB - 1);
+       LinearAddressStart <= LinearAddressEnd;
+       LinearAddressStart += SIZE_4KB) {
+    if (!IsLinearAddressValid (Cr0, Cr3, Cr4, LinearAddressStart)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
index 1b51034c25..075f668290 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
@@ -346,5 +346,23 @@ IsLinearAddressValid (
   IN  UINTN              LinearAddress
   );
 
+/**
+  Check if a linear address range is valid.
+
+  @param[in]  Cr0                 CR0 control register.
+  @param[in]  Cr3                 CR3 control register.
+  @param[in]  Cr4                 CR4 control register.
+  @param[in]  LinearAddressStart  Linear address start.
+  @param[in]  LinearAddressEnd    Linear address end.
+**/
+BOOLEAN
+IsLinearAddressRangeValid (
+  IN  UINTN              Cr0,
+  IN  UINTN              Cr3,
+  IN  UINTN              Cr4,
+  IN  UINTN              LinearAddressStart,
+  IN  UINTN              LinearAddressEnd
+  );
+
 #endif
 
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
index 71d2d2f5d4..4d8c9b0a89 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
@@ -415,6 +415,8 @@ DumpStackContents (
   UINTN   Cr0;
   UINTN   Cr3;
   UINTN   Cr4;
+  UINTN   RspAddressStart;
+  UINTN   RspAddressEnd;
 
   //
   // Get current stack pointer
@@ -436,21 +438,29 @@ DumpStackContents (
   Cr3 = SystemContext.SystemContextX64->Cr3;
   Cr4 = SystemContext.SystemContextX64->Cr4;
 
+  //
+  // Calculate address range of the stack pointers
+  //
+  RspAddressStart = (UINTN)CurrentRsp;
+  RspAddressEnd =
+    RspAddressStart + (UINTN)UnwoundStacksCount * CPU_STACK_ALIGNMENT;
+
+  //
+  // Validate address range of stack pointers
+  //
+  if (!IsLinearAddressRangeValid (Cr0, Cr3, Cr4, RspAddressStart,
+                                  RspAddressEnd)) {
+    InternalPrintMessage ("%a: attempted to dereference an invalid stack "
+                          "pointer at 0x%016lx - 0x%016lx\n", __FUNCTION__,
+                          RspAddressStart, RspAddressEnd);
+    return;
+  }
+
   //
   // Dump out stack contents
   //
   InternalPrintMessage ("\nStack dump:\n");
   while (UnwoundStacksCount-- > 0) {
-    //
-    // Check for a valid stack pointer address
-    //
-    if (!IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)CurrentRsp) ||
-        !IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)CurrentRsp + 8)) {
-      InternalPrintMessage ("%a: attempted to dereference an invalid stack "
-                            "pointer at 0x%016lx\n", __FUNCTION__, CurrentRsp);
-      break;
-    }
-
     InternalPrintMessage (
       "0x%016lx: %016lx %016lx\n",
       CurrentRsp,
@@ -459,7 +469,7 @@ DumpStackContents (
       );
 
     //
-    // Point to next stack
+    // Point to next stack pointer
     //
     CurrentRsp += CPU_STACK_ALIGNMENT;
   }
@@ -571,8 +581,8 @@ DumpImageModuleNames (
     //
     // Check for a valid frame pointer
     //
-    if (!IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)Rbp + 8) ||
-        !IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)Rbp)) {
+    if (!IsLinearAddressRangeValid (Cr0, Cr3, Cr4, (UINTN)Rbp,
+                                    (UINTN)Rbp + 8)) {
       InternalPrintMessage ("%a: attempted to dereference an invalid frame "
                             "pointer at 0x%016lx\n", __FUNCTION__, Rbp);
       break;
@@ -722,8 +732,8 @@ DumpStacktrace (
     //
     // Check for valid frame pointer
     //
-    if (!IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)Rbp + 8) ||
-        !IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)Rbp)) {
+    if (!IsLinearAddressRangeValid (Cr0, Cr3, Cr4, (UINTN)Rbp,
+                                    (UINTN)Rbp + 8)) {
       InternalPrintMessage ("%a: attempted to dereference an invalid frame "
                             "pointer at 0x%016lx\n", __FUNCTION__, Rbp);
       break;
-- 
2.14.3

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel