]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmmCore.c
QuarkSocPkg/QncSmmDispatcher: Fix use after free issue
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Smm / DxeSmm / QncSmmDispatcher / QNCSmmCore.c
index ba8c72177361af77cc9c08ac11c503109ef853c6..c2f75f86647ad4334ebfff2230dc68c559483132 100644 (file)
@@ -2,7 +2,7 @@
 This driver is responsible for the registration of child drivers\r
 and the abstraction of the QNC SMI sources.\r
 \r
-Copyright (c) 2013-2015 Intel Corporation.\r
+Copyright (c) 2013-2016 Intel Corporation.\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
@@ -351,7 +351,8 @@ Returns:
   // Gather information about the registration request\r
   //\r
   Record->Callback          = DispatchFunction;\r
-  Record->ChildContext      = *RegisterContext;\r
+  Record->CallbackContext   = RegisterContext;\r
+  CopyMem (&Record->ChildContext, RegisterContext, sizeof (QNC_SMM_CONTEXT));\r
 \r
   Qualified                 = QUALIFIED_PROTOCOL_FROM_GENERIC (This);\r
 \r
@@ -407,7 +408,7 @@ Returns:
       //\r
       // Update ChildContext again as SwSmiInputValue has been changed\r
       //\r
-      Record->ChildContext = *RegisterContext;\r
+      CopyMem (&Record->ChildContext, RegisterContext, sizeof (QNC_SMM_CONTEXT));\r
     }\r
 \r
     //\r
@@ -591,6 +592,7 @@ QNCSmmCoreDispatcher (
   BOOLEAN             ChildWasDispatched;\r
 \r
   DATABASE_RECORD     *RecordInDb;\r
+  DATABASE_RECORD     ActiveRecordInDb;\r
   LIST_ENTRY          *LinkInDb;\r
   DATABASE_RECORD     *RecordToExhaust;\r
   LIST_ENTRY          *LinkToExhaust;\r
@@ -612,6 +614,16 @@ QNCSmmCoreDispatcher (
   Status                = EFI_WARN_INTERRUPT_SOURCE_PENDING;\r
   ChildWasDispatched    = FALSE;\r
 \r
+  //\r
+  // Mark all child handlers as not processed\r
+  //\r
+  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {\r
+    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+    RecordInDb->Processed = FALSE;\r
+    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);\r
+  }\r
+\r
   //\r
   // Preserve Index registers\r
   //\r
@@ -633,6 +645,12 @@ QNCSmmCoreDispatcher (
 \r
       while ((!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) && (ResetListSearch == FALSE)) {\r
         RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+        //\r
+        // Make a copy of the record that contains an active SMI source,\r
+        // because un-register maybe invoked in callback function and\r
+        // RecordInDb maybe released\r
+        //\r
+        CopyMem (&ActiveRecordInDb, RecordInDb, sizeof (ActiveRecordInDb));\r
 \r
         //\r
         // look for the first active source\r
@@ -662,6 +680,13 @@ QNCSmmCoreDispatcher (
           //\r
           while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {\r
             RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);\r
+            LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, LinkToExhaust);\r
+            if (RecordToExhaust->Processed) {\r
+              //\r
+              // Record has already been processed.  Continue with next child handler.\r
+              //\r
+              continue;\r
+            }\r
 \r
             if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {\r
               //\r
@@ -688,10 +713,14 @@ QNCSmmCoreDispatcher (
                 // it supplied in registration.  Simply pass back what it gave us.\r
                 //\r
                 ASSERT (RecordToExhaust->Callback != NULL);\r
-                Context       = RecordToExhaust->ChildContext;\r
                 ContextsMatch = TRUE;\r
               }\r
 \r
+              //\r
+              // Mark this child handler so it will not be processed again\r
+              //\r
+              RecordToExhaust->Processed = TRUE;\r
+\r
               if (ContextsMatch) {\r
 \r
                 if (RecordToExhaust->BufferSize != 0) {\r
@@ -710,7 +739,7 @@ QNCSmmCoreDispatcher (
 \r
                 RecordToExhaust->Callback (\r
                                    (EFI_HANDLE) & RecordToExhaust->Link,\r
-                                   &Context,\r
+                                   RecordToExhaust->CallbackContext,\r
                                    CommunicationBuffer,\r
                                    &BufferSize\r
                                    );\r
@@ -720,11 +749,13 @@ QNCSmmCoreDispatcher (
                   SxChildWasDispatched = TRUE;\r
                 }\r
               }\r
+              //\r
+              // Can not use RecordInDb after this point because Callback may have unregistered RecordInDb\r
+              // Restart processing of SMI handlers from the begining of the linked list because the\r
+              // state of the linked listed may have been modified due to unregister actions in the Callback.\r
+              //\r
+              LinkToExhaust = GetFirstNode (&mPrivateData.CallbackDataBase);\r
             }\r
-            //\r
-            // Get next record in DB\r
-            //\r
-            LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);\r
           }\r
 \r
           if (RecordInDb->ClearSource == NULL) {\r
@@ -736,7 +767,7 @@ QNCSmmCoreDispatcher (
             //\r
             // This source requires special handling to clear\r
             //\r
-            RecordInDb->ClearSource (&ActiveSource);\r
+            ActiveRecordInDb.ClearSource (&ActiveSource);\r
           }\r
 \r
           if (ChildWasDispatched) {\r