From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id D796C81DB7 for ; Wed, 9 Nov 2016 23:42:20 -0800 (PST) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga104.fm.intel.com with ESMTP; 09 Nov 2016 23:42:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,617,1473145200"; d="scan'208";a="29570065" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by fmsmga006.fm.intel.com with ESMTP; 09 Nov 2016 23:42:23 -0800 Received: from FMSMSX109.amr.corp.intel.com (10.18.116.9) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.248.2; Wed, 9 Nov 2016 23:42:24 -0800 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by fmsmsx109.amr.corp.intel.com (10.18.116.9) with Microsoft SMTP Server (TLS) id 14.3.248.2; Wed, 9 Nov 2016 23:42:22 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.239]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.96]) with mapi id 14.03.0248.002; Thu, 10 Nov 2016 15:42:21 +0800 From: "Zhang, Chao B" To: "Ni, Ruiyu" , "edk2-devel@lists.01.org" CC: "Gao, Liming" , "Yao, Jiewen" Thread-Topic: [PATCH 1/4] MdeModulePkg/SecurityStubDxe: Defer 3rd party image before EndOfDxe Thread-Index: AQHSNjbBTy2bXL7t0EqK42m5moqqTqDR32oA Date: Thu, 10 Nov 2016 07:42:20 +0000 Message-ID: References: <20161104005942.345832-1-ruiyu.ni@intel.com> <20161104005942.345832-2-ruiyu.ni@intel.com> In-Reply-To: <20161104005942.345832-2-ruiyu.ni@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ctpclassification: CTP_IC x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiM2ZhNTRhOTYtMTRkNi00OTgwLTkyY2ItNzk4ODMzZDBhNWU4IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE1LjkuNi42IiwiVHJ1c3RlZExhYmVsSGFzaCI6IkJjTnVDQ0F2VGl4QVE5YWRsYmgrZjVGckloV0FlVkxmWmU5Q2h3XC9Gc0FZPSJ9 x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH 1/4] MdeModulePkg/SecurityStubDxe: Defer 3rd party image before EndOfDxe X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 Nov 2016 07:42:21 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by : Chao Zhang Thanks & Best regards Chao Zhang -----Original Message----- From: Ni, Ruiyu=20 Sent: Friday, November 04, 2016 9:00 AM To: edk2-devel@lists.01.org Cc: Gao, Liming; Yao, Jiewen; Zhang, Chao B Subject: [PATCH 1/4] MdeModulePkg/SecurityStubDxe: Defer 3rd party image be= fore EndOfDxe Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni Cc: Liming Gao Cc: Jiewen Yao Cc: Chao B Zhang --- .../SecurityStubDxe/Defer3rdPartyImageLoad.c | 356 +++++++++++++++++= ++++ .../SecurityStubDxe/Defer3rdPartyImageLoad.h | 92 ++++++ .../Universal/SecurityStubDxe/SecurityStub.c | 14 +- .../Universal/SecurityStubDxe/SecurityStubDxe.inf | 8 +- 4 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyIma= geLoad.c create mode 100644 MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyIma= geLoad.h diff --git a/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.= c b/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c new file mode 100644 index 0000000..ca45d56 --- /dev/null +++ b/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c @@ -0,0 +1,356 @@ +/** @file + Implement defer image load services for user identification in UEFI2.2. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD = License +which accompanies this distribution. The full text of the license may be = found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ +#include "Defer3rdPartyImageLoad.h" + +// +// The structure to save the deferred 3rd party image information. +// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + BOOLEAN BootOption; + BOOLEAN Loaded; +} DEFERRED_3RD_PARTY_IMAGE_INFO; + +// +// The table to save the deferred 3rd party image item. +// +typedef struct { + UINTN Count; ///< deferred 3rd party= image count + DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; ///< deferred 3rd party= image item +} DEFERRED_3RD_PARTY_IMAGE_TABLE; + +BOOLEAN mEndOfDxe =3D FALSE; +DEFERRED_3RD_PARTY_IMAGE_TABLE mDeferred3rdPartyImage =3D { + 0, // Deferred image count + NULL // The deferred image info +}; + +EFI_DEFERRED_IMAGE_LOAD_PROTOCOL mDeferredImageLoad =3D { + GetDefferedImageInfo +}; + +/** + Return whether the file comes from FV. + + @param[in] File This is a pointer to the device path of the file + that is being dispatched. + + @retval TRUE File comes from FV. + @retval FALSE File doesn't come from FV. +**/ +BOOLEAN +FileFromFv ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *File + ) +{ + EFI_STATUS Status; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + + // + // First check to see if File is from a Firmware Volume + // + DeviceHandle =3D NULL; + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) File; + Status =3D gBS->LocateDevicePath ( + &gEfiFirmwareVolume2ProtocolGuid, + &TempDevicePath, + &DeviceHandle + ); + if (!EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Find the deferred image which matches the device path. + + @param[in] ImageDevicePath A pointer to the device path of a image. + @param[in] BootOption Whether the image is a boot option. + + @return Pointer to the found deferred image or NULL if not found. +**/ +DEFERRED_3RD_PARTY_IMAGE_INFO * +LookupImage ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath, + IN BOOLEAN BootOption + ) +{ + UINTN Index; + UINTN DevicePathSize; + + DevicePathSize =3D GetDevicePathSize (ImageDevicePath); + + for (Index =3D 0; Index < mDeferred3rdPartyImage.Count; Index++) { + if (CompareMem (ImageDevicePath, mDeferred3rdPartyImage.ImageInfo[Inde= x].ImageDevicePath, DevicePathSize) =3D=3D 0) { + ASSERT (mDeferred3rdPartyImage.ImageInfo[Index].BootOption =3D=3D Bo= otOption); + return &mDeferred3rdPartyImage.ImageInfo[Index]; + } + } + + return NULL; +} + +/** + Add the image info to a deferred image list. + + @param[in] ImageDevicePath A pointer to the device path of a image. + @param[in] BootOption Whether the image is a boot option. + +**/ +VOID +QueueImage ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath, + IN BOOLEAN BootOption + ) +{ + DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; + + // + // Expand memory for the new deferred image. + // + ImageInfo =3D ReallocatePool ( + mDeferred3rdPartyImage.Count * sizeof (DEFERRED_3RD_PARTY_= IMAGE_INFO), + (mDeferred3rdPartyImage.Count + 1) * sizeof (DEFERRED_3RD_= PARTY_IMAGE_INFO), + mDeferred3rdPartyImage.ImageInfo + ); + if (ImageInfo =3D=3D NULL) { + return; + } + mDeferred3rdPartyImage.ImageInfo =3D ImageInfo; + + // + // Save the deferred image information. + // + ImageInfo =3D &mDeferred3rdPartyImage.ImageInfo[mDeferred3rdPartyImage.C= ount]; + ImageInfo->ImageDevicePath =3D DuplicateDevicePath (ImageDevicePath); + if (ImageInfo->ImageDevicePath =3D=3D NULL) { + return; + } + ImageInfo->BootOption =3D BootOption; + ImageInfo->Loaded =3D FALSE; + mDeferred3rdPartyImage.Count++; +} + + +/** + Returns information about a deferred image. + + This function returns information about a single deferred image. The def= erred images are + numbered consecutively, starting with 0. If there is no image which cor= responds to + ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be r= eturned by + iteratively calling this function until EFI_NOT_FOUND is returned. + Image may be NULL and ImageSize set to 0 if the decision to defer execut= ion was made + because of the location of the executable image, rather than its actual = contents. + + @param[in] This Points to this instance of the EFI_DEFERRED= _IMAGE_LOAD_PROTOCOL. + @param[in] ImageIndex Zero-based index of the deferred index. + @param[out] ImageDevicePath On return, points to a pointer to the devic= e path of the image. + The device path should not be freed by the = caller. + @param[out] Image On return, points to the first byte of the = image or NULL if the + image is not available. The image should no= t be freed by the caller + unless LoadImage() has been successfully ca= lled. + @param[out] ImageSize On return, the size of the image, or 0 if t= he image is not available. + @param[out] BootOption On return, points to TRUE if the image was = intended as a boot option + or FALSE if it was not intended as a boot o= ption. + + @retval EFI_SUCCESS Image information returned successfully. + @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image= . + @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL o= r ImageSize is NULL or + BootOption is NULL. + +**/ +EFI_STATUS +EFIAPI +GetDefferedImageInfo ( + IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This, + IN UINTN ImageIndex, + OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath, + OUT VOID **Image, + OUT UINTN *ImageSize, + OUT BOOLEAN *BootOption + ) +{ + UINTN Index; + UINTN NewCount; + + if ((This =3D=3D NULL) || (ImageSize =3D=3D NULL) || (Image =3D=3D NULL)= ) { + return EFI_INVALID_PARAMETER; + } + + if ((ImageDevicePath =3D=3D NULL) || (BootOption =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Remove the loaded images from the defer list in the first call. + // + if (ImageIndex =3D=3D 0) { + NewCount =3D 0; + for (Index =3D 0; Index < mDeferred3rdPartyImage.Count; Index++) { + if (!mDeferred3rdPartyImage.ImageInfo[Index].Loaded) { + CopyMem ( + &mDeferred3rdPartyImage.ImageInfo[NewCount], + &mDeferred3rdPartyImage.ImageInfo[Index], + sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO) + ); + NewCount++; + } + } + + mDeferred3rdPartyImage.Count =3D NewCount; + } + + if (ImageIndex >=3D mDeferred3rdPartyImage.Count) { + return EFI_NOT_FOUND; + } + + // + // Get the request deferred image. + // + *ImageDevicePath =3D mDeferred3rdPartyImage.ImageInfo[ImageIndex].ImageD= evicePath; + *BootOption =3D mDeferred3rdPartyImage.ImageInfo[ImageIndex].BootOp= tion; + *Image =3D NULL; + *ImageSize =3D 0; + + return EFI_SUCCESS; +} + +/** + Callback function executed when the EndOfDxe event group is signaled. + + @param[in] Event Event whose notification function is being invoked= . + @param[in] Context The pointer to the notification function's context= , which + is implementation-dependent. +**/ +VOID +EFIAPI +EndOfDxe ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mEndOfDxe =3D TRUE; +} + +/** + Defer the 3rd party image load and installs Deferred Image Load Protocol= . + + @param[in] File This is a pointer to the device path o= f the file that + is being dispatched. This will optiona= lly be used for + logging. + @param[in] BootPolicy A boot policy that was used to call Lo= adImage() UEFI service. + + @retval EFI_SUCCESS The file is not 3rd party image and ca= n be loaded immediately. + @retval EFI_ACCESS_DENIED The file is 3rd party image and needs = deferred. +**/ +EFI_STATUS +Defer3rdPartyImageLoad ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *File, + IN BOOLEAN BootPolicy + ) +{ + DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; + + // + // Ignore if File is NULL. + // + if (File =3D=3D NULL) { + return EFI_SUCCESS; + } + + if (FileFromFv (File)) { + return EFI_SUCCESS; + } + + ImageInfo =3D LookupImage (File, BootPolicy); + + DEBUG_CODE ( + CHAR16 *DevicePathStr; + DevicePathStr =3D ConvertDevicePathToText (File, FALSE, FALSE); + DEBUG (( + DEBUG_INFO, + "[Security] 3rd party image[%p] %s EndOfDxe: %s.\n", ImageInfo, + mEndOfDxe ? L"can be loaded after": L"is deferred to load before", + DevicePathStr + )); + if (DevicePathStr !=3D NULL) { + FreePool (DevicePathStr); + } + ); + + if (mEndOfDxe) { + // + // The image might be first time loaded after EndOfDxe, + // So ImageInfo can be NULL. + // + if (ImageInfo !=3D NULL) { + ImageInfo->Loaded =3D TRUE; + } + return EFI_SUCCESS; + } else { + // + // The image might be second time loaded before EndOfDxe, + // So ImageInfo can be non-NULL. + // + if (ImageInfo =3D=3D NULL) { + QueueImage (File, BootPolicy); + } + return EFI_ACCESS_DENIED; + } +} + +/** + Installs DeferredImageLoad Protocol and listens EndOfDxe event. +**/ +VOID +Defer3rdPartyImageLoadInitialize ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_EVENT Event; + + Handle =3D NULL; + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiDeferredImageLoadProtocolGuid, + &mDeferredImageLoad, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + EndOfDxe, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); +} diff --git a/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.= h b/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.h new file mode 100644 index 0000000..3fab258 --- /dev/null +++ b/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.h @@ -0,0 +1,92 @@ +/** @file + Implement defer image load services for user identification in UEFI2.2. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD = License +which accompanies this distribution. The full text of the license may be = found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#ifndef _DEFER_3RD_PARTY_IMAGE_LOAD_H_ +#define _DEFER_3RD_PARTY_IMAGE_LOAD_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/** + Returns information about a deferred image. + + This function returns information about a single deferred image. The def= erred images are + numbered consecutively, starting with 0. If there is no image which cor= responds to + ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be r= eturned by + iteratively calling this function until EFI_NOT_FOUND is returned. + Image may be NULL and ImageSize set to 0 if the decision to defer execut= ion was made + because of the location of the executable image, rather than its actual = contents. + + @param[in] This Points to this instance of the EFI_DEFERRED= _IMAGE_LOAD_PROTOCOL. + @param[in] ImageIndex Zero-based index of the deferred index. + @param[out] ImageDevicePath On return, points to a pointer to the devic= e path of the image. + The device path should not be freed by the = caller. + @param[out] Image On return, points to the first byte of the = image or NULL if the + image is not available. The image should no= t be freed by the caller + unless LoadImage() has been successfully ca= lled. + @param[out] ImageSize On return, the size of the image, or 0 if t= he image is not available. + @param[out] BootOption On return, points to TRUE if the image was = intended as a boot option + or FALSE if it was not intended as a boot o= ption. + + @retval EFI_SUCCESS Image information returned successfully. + @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image= . + @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL o= r ImageSize is NULL or + BootOption is NULL. + +**/ +EFI_STATUS +EFIAPI +GetDefferedImageInfo ( + IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This, + IN UINTN ImageIndex, + OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath, + OUT VOID **Image, + OUT UINTN *ImageSize, + OUT BOOLEAN *BootOption + ); + +/** + Defer the 3rd party image load and installs Deferred Image Load Protocol= . + + @param[in] File This is a pointer to the device path o= f the file that + is being dispatched. This will optiona= lly be used for + logging. + @param[in] BootPolicy A boot policy that was used to call Lo= adImage() UEFI service. + + @retval EFI_SUCCESS The file is not 3rd party image and ca= n be loaded immediately. + @retval EFI_ACCESS_DENIED The file is 3rd party image and needs = deferred. +**/ +EFI_STATUS +Defer3rdPartyImageLoad ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *File, + IN BOOLEAN BootPolicy + ); + +/** + Installs DeferredImageLoad Protocol and listens EndOfDxe event. +**/ +VOID +Defer3rdPartyImageLoadInitialize ( + VOID + ); + +#endif diff --git a/MdeModulePkg/Universal/SecurityStubDxe/SecurityStub.c b/MdeMod= ulePkg/Universal/SecurityStubDxe/SecurityStub.c index 22e6c7f..a75d8dc 100644 --- a/MdeModulePkg/Universal/SecurityStubDxe/SecurityStub.c +++ b/MdeModulePkg/Universal/SecurityStubDxe/SecurityStub.c @@ -1,7 +1,7 @@ /** @file This driver produces Security2 and Security architectural protocol based= on SecurityManagementLib. =20 - Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials =20 are licensed and made available under the terms and conditions of the BS= D License =20 which accompanies this distribution. The full text of the license may b= e found at =20 @@ -20,6 +20,7 @@ #include #include #include +#include "Defer3rdPartyImageLoad.h" =20 // // Handle for the Security Architectural Protocol instance produced by thi= s driver @@ -140,6 +141,15 @@ Security2StubAuthenticate ( IN BOOLEAN BootPolicy ) { + EFI_STATUS Status; + + if (FileBuffer !=3D NULL) { + Status =3D Defer3rdPartyImageLoad (File, BootPolicy); + if (EFI_ERROR (Status)) { + return Status; + } + } + return ExecuteSecurity2Handlers (EFI_AUTH_OPERATION_VERIFY_IMAGE |=20 EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD |=20 EFI_AUTH_OPERATION_MEASURE_IMAGE | @@ -200,5 +210,7 @@ SecurityStubInitialize ( ); ASSERT_EFI_ERROR (Status); =20 + Defer3rdPartyImageLoadInitialize (); + return EFI_SUCCESS; } diff --git a/MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf b/M= deModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf index 9d1c7b8..be6ce6c 100644 --- a/MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +++ b/MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf @@ -1,7 +1,7 @@ ## @file # This driver produces security2 and security architectural protocol base= d on SecurityManagementLib. # -# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License # which accompanies this distribution. The full text of the license may b= e found at @@ -29,6 +29,8 @@ [Defines] =20 [Sources] SecurityStub.c + Defer3rdPartyImageLoad.c + Defer3rdPartyImageLoad.h =20 [Packages] MdePkg/MdePkg.dec @@ -40,9 +42,13 @@ [LibraryClasses] DebugLib SecurityManagementLib =20 +[Guids] + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + [Protocols] gEfiSecurityArchProtocolGuid ## PRODUCES gEfiSecurity2ArchProtocolGuid ## PRODUCES + gEfiDeferredImageLoadProtocolGuid ## PRODUCES =20 [Depex] TRUE --=20 2.9.0.windows.1