Reviewed-by: Liming Gao <liming....@intel.com>
> -----Original Message----- > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of > Ruiyu Ni > Sent: Tuesday, November 08, 2016 8:29 PM > To: edk2-devel@lists.01.org > Cc: Yao, Jiewen <jiewen....@intel.com>; Zhang, Chao B > <chao.b.zh...@intel.com>; Gao, Liming <liming....@intel.com> > Subject: [edk2] [PATCH v2 1/9] MdeModulePkg/SecurityStubDxe: Defer 3rd > party image before EndOfDxe > > The images not from FV are treated as 3rd party images. They will > be deferred to dispatch when they are dispatched before EndOfDxe > event. > It's a new feature in the BS.LoadImage() path which can disallow > executing 3rd party images before EndOfDxe and re-execute them > after EndOfDxe (through EfiBootManagerDispatchDeferredImages > introduced in next commit). > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ruiyu Ni <ruiyu...@intel.com> > Cc: Liming Gao <liming....@intel.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Chao B Zhang <chao.b.zh...@intel.com> > --- > .../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/Defer3rdPartyImageLoad.c > create mode 100644 > MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.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.<BR> > +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 IMPLIED. > + > +**/ > +#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 = FALSE; > +DEFERRED_3RD_PARTY_IMAGE_TABLE mDeferred3rdPartyImage = { > + 0, // Deferred image count > + NULL // The deferred image info > +}; > + > +EFI_DEFERRED_IMAGE_LOAD_PROTOCOL mDeferredImageLoad = { > + 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 = NULL; > + TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File; > + Status = gBS->LocateDevicePath ( > + &gEfiFirmwareVolume2ProtocolGuid, > + &TempDevicePath, > + &DeviceHandle > + ); > + if (!EFI_ERROR (Status)) { > + Status = 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 = GetDevicePathSize (ImageDevicePath); > + > + for (Index = 0; Index < mDeferred3rdPartyImage.Count; Index++) { > + if (CompareMem (ImageDevicePath, > mDeferred3rdPartyImage.ImageInfo[Index].ImageDevicePath, > DevicePathSize) == 0) { > + ASSERT (mDeferred3rdPartyImage.ImageInfo[Index].BootOption == > BootOption); > + 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 = ReallocatePool ( > + mDeferred3rdPartyImage.Count * sizeof > (DEFERRED_3RD_PARTY_IMAGE_INFO), > + (mDeferred3rdPartyImage.Count + 1) * sizeof > (DEFERRED_3RD_PARTY_IMAGE_INFO), > + mDeferred3rdPartyImage.ImageInfo > + ); > + if (ImageInfo == NULL) { > + return; > + } > + mDeferred3rdPartyImage.ImageInfo = ImageInfo; > + > + // > + // Save the deferred image information. > + // > + ImageInfo = > &mDeferred3rdPartyImage.ImageInfo[mDeferred3rdPartyImage.Count]; > + ImageInfo->ImageDevicePath = DuplicateDevicePath (ImageDevicePath); > + if (ImageInfo->ImageDevicePath == NULL) { > + return; > + } > + ImageInfo->BootOption = BootOption; > + ImageInfo->Loaded = FALSE; > + mDeferred3rdPartyImage.Count++; > +} > + > + > +/** > + Returns information about a deferred image. > + > + This function returns information about a single deferred image. The > deferred images are > + numbered consecutively, starting with 0. If there is no image which > corresponds to > + ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may > be returned 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 > execution 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 > device 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 not > be freed by the > caller > + unless LoadImage() has been successfully > called. > + @param[out] ImageSize On return, the size of the image, or 0 if the > 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 > option. > + > + @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 or 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 == NULL) || (ImageSize == NULL) || (Image == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((ImageDevicePath == NULL) || (BootOption == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Remove the loaded images from the defer list in the first call. > + // > + if (ImageIndex == 0) { > + NewCount = 0; > + for (Index = 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 = NewCount; > + } > + > + if (ImageIndex >= mDeferred3rdPartyImage.Count) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Get the request deferred image. > + // > + *ImageDevicePath = > mDeferred3rdPartyImage.ImageInfo[ImageIndex].ImageDevicePath; > + *BootOption = > mDeferred3rdPartyImage.ImageInfo[ImageIndex].BootOption; > + *Image = NULL; > + *ImageSize = 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 = TRUE; > +} > + > +/** > + Defer the 3rd party image load and installs Deferred Image Load Protocol. > + > + @param[in] File This is a pointer to the device path of > the file that > + is being dispatched. This will > optionally be used for > + logging. > + @param[in] BootPolicy A boot policy that was used to call > LoadImage() UEFI service. > + > + @retval EFI_SUCCESS The file is not 3rd party image and can > 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 == NULL) { > + return EFI_SUCCESS; > + } > + > + if (FileFromFv (File)) { > + return EFI_SUCCESS; > + } > + > + ImageInfo = LookupImage (File, BootPolicy); > + > + DEBUG_CODE ( > + CHAR16 *DevicePathStr; > + DevicePathStr = 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 != NULL) { > + FreePool (DevicePathStr); > + } > + ); > + > + if (mEndOfDxe) { > + // > + // The image might be first time loaded after EndOfDxe, > + // So ImageInfo can be NULL. > + // > + if (ImageInfo != NULL) { > + ImageInfo->Loaded = TRUE; > + } > + return EFI_SUCCESS; > + } else { > + // > + // The image might be second time loaded before EndOfDxe, > + // So ImageInfo can be non-NULL. > + // > + if (ImageInfo == 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 = NULL; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &Handle, > + &gEfiDeferredImageLoadProtocolGuid, > + &mDeferredImageLoad, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + > + Status = 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.<BR> > +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 IMPLIED. > + > +**/ > + > +#ifndef _DEFER_3RD_PARTY_IMAGE_LOAD_H_ > +#define _DEFER_3RD_PARTY_IMAGE_LOAD_H_ > + > +#include <Uefi.h> > +#include <Guid/EventGroup.h> > +#include <Protocol/DeferredImageLoad.h> > +#include <Protocol/FirmwareVolume2.h> > + > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/DevicePathLib.h> > +#include <Library/DebugLib.h> > + > +/** > + Returns information about a deferred image. > + > + This function returns information about a single deferred image. The > deferred images are > + numbered consecutively, starting with 0. If there is no image which > corresponds to > + ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may > be returned 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 > execution 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 > device 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 not > be freed by the > caller > + unless LoadImage() has been successfully > called. > + @param[out] ImageSize On return, the size of the image, or 0 if the > 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 > option. > + > + @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 or 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 of > the file that > + is being dispatched. This will > optionally be used for > + logging. > + @param[in] BootPolicy A boot policy that was used to call > LoadImage() UEFI service. > + > + @retval EFI_SUCCESS The file is not 3rd party image and can > 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/MdeModulePkg/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. > > - Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> > 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 > @@ -20,6 +20,7 @@ > #include <Library/UefiBootServicesTableLib.h> > #include <Library/UefiDriverEntryPoint.h> > #include <Library/SecurityManagementLib.h> > +#include "Defer3rdPartyImageLoad.h" > > // > // Handle for the Security Architectural Protocol instance produced by this > driver > @@ -140,6 +141,15 @@ Security2StubAuthenticate ( > IN BOOLEAN BootPolicy > ) > { > + EFI_STATUS Status; > + > + if (FileBuffer != NULL) { > + Status = Defer3rdPartyImageLoad (File, BootPolicy); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > return ExecuteSecurity2Handlers (EFI_AUTH_OPERATION_VERIFY_IMAGE > | > EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD | > EFI_AUTH_OPERATION_MEASURE_IMAGE | > @@ -200,5 +210,7 @@ SecurityStubInitialize ( > ); > ASSERT_EFI_ERROR (Status); > > + Defer3rdPartyImageLoadInitialize (); > + > return EFI_SUCCESS; > } > diff --git a/MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf > b/MdeModulePkg/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 based > on > SecurityManagementLib. > # > -# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> > +# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> > # 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 > @@ -29,6 +29,8 @@ [Defines] > > [Sources] > SecurityStub.c > + Defer3rdPartyImageLoad.c > + Defer3rdPartyImageLoad.h > > [Packages] > MdePkg/MdePkg.dec > @@ -40,9 +42,13 @@ [LibraryClasses] > DebugLib > SecurityManagementLib > > +[Guids] > + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event > + > [Protocols] > gEfiSecurityArchProtocolGuid ## PRODUCES > gEfiSecurity2ArchProtocolGuid ## PRODUCES > + gEfiDeferredImageLoadProtocolGuid ## PRODUCES > > [Depex] > TRUE > -- > 2.9.0.windows.1 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel