TianoCore EDK2 master
Loading...
Searching...
No Matches
MemoryProtection.c
Go to the documentation of this file.
1
27#include <PiDxe.h>
28#include <Library/BaseLib.h>
33#include <Library/DebugLib.h>
34#include <Library/UefiLib.h>
36
37#include <Guid/EventGroup.h>
39
42
43#include "DxeMain.h"
44#include "Mem/HeapGuard.h"
45
46//
47// Image type definitions
48//
49#define IMAGE_UNKNOWN 0x00000001
50#define IMAGE_FROM_FV 0x00000002
51
52//
53// Protection policy bit definition
54//
55#define DO_NOT_PROTECT 0x00000000
56#define PROTECT_IF_ALIGNED_ELSE_ALLOW 0x00000001
57
58#define MEMORY_TYPE_OS_RESERVED_MIN 0x80000000
59#define MEMORY_TYPE_OEM_RESERVED_MIN 0x70000000
60
61#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
62 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
63
64UINT32 mImageProtectionPolicy;
65
66extern LIST_ENTRY mGcdMemorySpaceMap;
67
68STATIC LIST_ENTRY mProtectedImageRecordList;
69
78UINT32
81 )
82{
83 EFI_STATUS Status;
84 EFI_HANDLE DeviceHandle;
85 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
86
87 if (File == NULL) {
88 return IMAGE_UNKNOWN;
89 }
90
91 //
92 // First check to see if File is from a Firmware Volume
93 //
94 DeviceHandle = NULL;
95 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
96 Status = gBS->LocateDevicePath (
97 &gEfiFirmwareVolume2ProtocolGuid,
98 &TempDevicePath,
99 &DeviceHandle
100 );
101 if (!EFI_ERROR (Status)) {
102 Status = gBS->OpenProtocol (
103 DeviceHandle,
104 &gEfiFirmwareVolume2ProtocolGuid,
105 NULL,
106 NULL,
107 NULL,
108 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
109 );
110 if (!EFI_ERROR (Status)) {
111 return IMAGE_FROM_FV;
112 }
113 }
114
115 return IMAGE_UNKNOWN;
116}
117
125UINT32
127 IN UINT32 ImageType
128 )
129{
130 if ((ImageType & mImageProtectionPolicy) == 0) {
131 return DO_NOT_PROTECT;
132 } else {
133 return PROTECT_IF_ALIGNED_ELSE_ALLOW;
134 }
135}
136
145UINT32
147 IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
148 IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
149 )
150{
151 BOOLEAN InSmm;
152 UINT32 ImageType;
153 UINT32 ProtectionPolicy;
154
155 //
156 // Check SMM
157 //
158 InSmm = FALSE;
159 if (gSmmBase2 != NULL) {
160 gSmmBase2->InSmm (gSmmBase2, &InSmm);
161 }
162
163 if (InSmm) {
164 return FALSE;
165 }
166
167 //
168 // Check DevicePath
169 //
170 if (LoadedImage == gDxeCoreLoadedImage) {
171 ImageType = IMAGE_FROM_FV;
172 } else {
173 ImageType = GetImageType (LoadedImageDevicePath);
174 }
175
176 ProtectionPolicy = GetProtectionPolicyFromImageType (ImageType);
177 return ProtectionPolicy;
178}
179
187VOID
189 IN UINT64 BaseAddress,
190 IN UINT64 Length,
191 IN UINT64 Attributes
192 )
193{
194 EFI_STATUS Status;
196 UINT64 FinalAttributes;
197
198 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
199 ASSERT_EFI_ERROR (Status);
200
201 FinalAttributes = (Descriptor.Attributes & EFI_CACHE_ATTRIBUTE_MASK) | (Attributes & EFI_MEMORY_ATTRIBUTE_MASK);
202
203 DEBUG ((DEBUG_INFO, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016lx (0x%016lx)\n", BaseAddress, Length, FinalAttributes));
204
205 ASSERT (gCpu != NULL);
206 gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes);
207}
208
214VOID
216 IN IMAGE_PROPERTIES_RECORD *ImageRecord
217 )
218{
219 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
220 LIST_ENTRY *ImageRecordCodeSectionLink;
221 LIST_ENTRY *ImageRecordCodeSectionEndLink;
222 LIST_ENTRY *ImageRecordCodeSectionList;
223 UINT64 CurrentBase;
224 UINT64 ImageEnd;
225
226 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
227
228 CurrentBase = ImageRecord->ImageBase;
229 ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
230
231 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
232 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
233 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
234 ImageRecordCodeSection = CR (
235 ImageRecordCodeSectionLink,
237 Link,
238 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
239 );
240 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
241
242 ASSERT (CurrentBase <= ImageRecordCodeSection->CodeSegmentBase);
243 if (CurrentBase < ImageRecordCodeSection->CodeSegmentBase) {
244 //
245 // DATA
246 //
248 CurrentBase,
249 ImageRecordCodeSection->CodeSegmentBase - CurrentBase,
250 EFI_MEMORY_XP
251 );
252 }
253
254 //
255 // CODE
256 //
258 ImageRecordCodeSection->CodeSegmentBase,
259 ImageRecordCodeSection->CodeSegmentSize,
260 EFI_MEMORY_RO
261 );
262 CurrentBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
263 }
264
265 //
266 // Last DATA
267 //
268 ASSERT (CurrentBase <= ImageEnd);
269 if (CurrentBase < ImageEnd) {
270 //
271 // DATA
272 //
274 CurrentBase,
275 ImageEnd - CurrentBase,
276 EFI_MEMORY_XP
277 );
278 }
279
280 return;
281}
282
291STATIC
292UINT32
294 IN EFI_MEMORY_TYPE MemoryType
295 )
296{
297 UINT32 SectionAlignment;
298
299 switch (MemoryType) {
301 case EfiACPIMemoryNVS:
303 SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
304 break;
306 ASSERT (FALSE);
307 SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
308 break;
310 case EfiLoaderCode:
311 SectionAlignment = EFI_PAGE_SIZE;
312 break;
314 default:
315 ASSERT (FALSE);
316 SectionAlignment = EFI_PAGE_SIZE;
317 break;
318 }
319
320 return SectionAlignment;
321}
322
329VOID
331 IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
332 IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
333 )
334{
335 IMAGE_PROPERTIES_RECORD *ImageRecord;
336 UINT32 ProtectionPolicy;
337 EFI_STATUS Status;
338 UINT32 RequiredAlignment;
339
340 DEBUG ((DEBUG_INFO, "ProtectUefiImageCommon - 0x%x\n", LoadedImage));
341 DEBUG ((DEBUG_INFO, " - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase, LoadedImage->ImageSize));
342
343 if (gCpu == NULL) {
344 return;
345 }
346
347 ProtectionPolicy = GetUefiImageProtectionPolicy (LoadedImage, LoadedImageDevicePath);
348 switch (ProtectionPolicy) {
349 case DO_NOT_PROTECT:
350 return;
351 case PROTECT_IF_ALIGNED_ELSE_ALLOW:
352 break;
353 default:
354 ASSERT (FALSE);
355 return;
356 }
357
358 ImageRecord = AllocateZeroPool (sizeof (*ImageRecord));
359 if (ImageRecord == NULL) {
360 return;
361 }
362
363 RequiredAlignment = GetMemoryProtectionSectionAlignment (LoadedImage->ImageCodeType);
364
366 LoadedImage->ImageBase,
367 LoadedImage->ImageSize,
368 &RequiredAlignment,
369 ImageRecord
370 );
371
372 if (EFI_ERROR (Status)) {
373 DEBUG ((DEBUG_ERROR, "%a failed to create image properties record\n", __func__));
374 FreePool (ImageRecord);
375 goto Finish;
376 }
377
378 //
379 // CPU ARCH present. Update memory attribute directly.
380 //
382
383 //
384 // Record the image record in the list so we can undo the protections later
385 //
386 InsertTailList (&mProtectedImageRecordList, &ImageRecord->Link);
387
388Finish:
389 return;
390}
391
398VOID
400 IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
401 IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
402 )
403{
404 IMAGE_PROPERTIES_RECORD *ImageRecord;
405 LIST_ENTRY *ImageRecordLink;
406
407 if (PcdGet32 (PcdImageProtectionPolicy) != 0) {
408 for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
409 ImageRecordLink != &mProtectedImageRecordList;
410 ImageRecordLink = ImageRecordLink->ForwardLink)
411 {
412 ImageRecord = CR (
413 ImageRecordLink,
415 Link,
416 IMAGE_PROPERTIES_RECORD_SIGNATURE
417 );
418
419 if (ImageRecord->ImageBase == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) {
421 ImageRecord->ImageBase,
422 ImageRecord->ImageSize,
423 0
424 );
425 DeleteImagePropertiesRecord (ImageRecord);
426 return;
427 }
428 }
429 }
430}
431
438STATIC
439UINT64
441 IN EFI_MEMORY_TYPE MemoryType
442 )
443{
444 UINT64 TestBit;
445
446 if ((UINT32)MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
447 TestBit = BIT63;
448 } else if ((UINT32)MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
449 TestBit = BIT62;
450 } else {
451 TestBit = LShiftU64 (1, MemoryType);
452 }
453
454 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & TestBit) != 0) {
455 return EFI_MEMORY_XP;
456 } else {
457 return 0;
458 }
459}
460
469STATIC
470VOID
472 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
473 IN UINTN MemoryMapSize,
474 IN UINTN DescriptorSize
475 )
476{
477 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
478 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
479 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
480 EFI_MEMORY_DESCRIPTOR TempMemoryMap;
481
482 MemoryMapEntry = MemoryMap;
483 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
484 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
485 while (MemoryMapEntry < MemoryMapEnd) {
486 while (NextMemoryMapEntry < MemoryMapEnd) {
487 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
488 CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
489 CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
490 CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
491 }
492
493 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
494 }
495
496 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
497 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
498 }
499}
500
512STATIC
513VOID
515 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
516 IN OUT UINTN *MemoryMapSize,
517 IN UINTN DescriptorSize
518 )
519{
520 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
521 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
522 UINT64 MemoryBlockLength;
523 EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
524 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
525 UINT64 Attributes;
526
527 SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
528
529 MemoryMapEntry = MemoryMap;
530 NewMemoryMapEntry = MemoryMap;
531 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
532 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
533 CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
534 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
535
536 do {
537 MemoryBlockLength = (UINT64)(EFI_PAGES_TO_SIZE ((UINTN)MemoryMapEntry->NumberOfPages));
538 Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
539
540 if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
541 (Attributes == GetPermissionAttributeForMemoryType (NextMemoryMapEntry->Type)) &&
542 ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
543 {
544 MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
545 if (NewMemoryMapEntry != MemoryMapEntry) {
546 NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
547 }
548
549 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
550 continue;
551 } else {
552 MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
553 break;
554 }
555 } while (TRUE);
556
557 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
558 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
559 }
560
561 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
562
563 return;
564}
565
570STATIC
571VOID
573 VOID
574 )
575{
576 UINTN MemoryMapSize;
577 UINTN MapKey;
578 UINTN DescriptorSize;
579 UINT32 DescriptorVersion;
580 EFI_MEMORY_DESCRIPTOR *MemoryMap;
581 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
582 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
583 EFI_STATUS Status;
584 UINT64 Attributes;
585 LIST_ENTRY *Link;
586 EFI_GCD_MAP_ENTRY *Entry;
588 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
589 EFI_PHYSICAL_ADDRESS StackBase;
590
591 //
592 // Get the EFI memory map.
593 //
594 MemoryMapSize = 0;
595 MemoryMap = NULL;
596
597 Status = gBS->GetMemoryMap (
598 &MemoryMapSize,
599 MemoryMap,
600 &MapKey,
601 &DescriptorSize,
602 &DescriptorVersion
603 );
604 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
605 do {
606 MemoryMap = (EFI_MEMORY_DESCRIPTOR *)AllocatePool (MemoryMapSize);
607 ASSERT (MemoryMap != NULL);
608 Status = gBS->GetMemoryMap (
609 &MemoryMapSize,
610 MemoryMap,
611 &MapKey,
612 &DescriptorSize,
613 &DescriptorVersion
614 );
615 if (EFI_ERROR (Status)) {
616 FreePool (MemoryMap);
617 }
618 } while (Status == EFI_BUFFER_TOO_SMALL);
619
620 ASSERT_EFI_ERROR (Status);
621
622 StackBase = 0;
623 if (PcdGetBool (PcdCpuStackGuard)) {
624 //
625 // Get the base of stack from Hob.
626 //
627 Hob.Raw = GetHobList ();
628 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
629 MemoryHob = Hob.MemoryAllocation;
630 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {
631 DEBUG ((
632 DEBUG_INFO,
633 "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n",
634 __func__,
637 ));
638
639 StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;
640 //
641 // Ensure the base of the stack is page-size aligned.
642 //
643 ASSERT ((StackBase & EFI_PAGE_MASK) == 0);
644 break;
645 }
646
647 Hob.Raw = GET_NEXT_HOB (Hob);
648 }
649
650 //
651 // Ensure the base of stack can be found from Hob when stack guard is
652 // enabled.
653 //
654 ASSERT (StackBase != 0);
655 }
656
657 DEBUG ((
658 DEBUG_INFO,
659 "%a: applying strict permissions to active memory regions\n",
660 __func__
661 ));
662
663 MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize);
664
665 MemoryMapEntry = MemoryMap;
666 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
667 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
668 Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
669 if (Attributes != 0) {
671 MemoryMapEntry->PhysicalStart,
672 LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT),
673 Attributes
674 );
675
676 //
677 // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is
678 // enabled.
679 //
680 if ((MemoryMapEntry->PhysicalStart == 0) &&
681 (PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0))
682 {
683 ASSERT (MemoryMapEntry->NumberOfPages > 0);
685 0,
687 EFI_MEMORY_RP | Attributes
688 );
689 }
690
691 //
692 // Add EFI_MEMORY_RP attribute for the first page of the stack if stack
693 // guard is enabled.
694 //
695 if ((StackBase != 0) &&
696 ((StackBase >= MemoryMapEntry->PhysicalStart) &&
697 (StackBase < MemoryMapEntry->PhysicalStart +
698 LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT))) &&
699 PcdGetBool (PcdCpuStackGuard))
700 {
702 StackBase,
704 EFI_MEMORY_RP | Attributes
705 );
706 }
707 }
708
709 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
710 }
711
712 FreePool (MemoryMap);
713
714 //
715 // Apply the policy for RAM regions that we know are present and
716 // accessible, but have not been added to the UEFI memory map (yet).
717 //
719 DEBUG ((
720 DEBUG_INFO,
721 "%a: applying strict permissions to inactive memory regions\n",
722 __func__
723 ));
724
726
727 Link = mGcdMemorySpaceMap.ForwardLink;
728 while (Link != &mGcdMemorySpaceMap) {
729 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
730
731 if ((Entry->GcdMemoryType == EfiGcdMemoryTypeReserved) &&
732 (Entry->EndAddress < MAX_ADDRESS) &&
733 ((Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
734 (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)))
735 {
737 (Entry->Attributes & EFI_CACHE_ATTRIBUTE_MASK);
738
739 DEBUG ((
740 DEBUG_INFO,
741 "Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n",
742 Entry->BaseAddress,
743 Entry->EndAddress - Entry->BaseAddress + 1,
744 Attributes
745 ));
746
747 ASSERT (gCpu != NULL);
748 gCpu->SetMemoryAttributes (
749 gCpu,
750 Entry->BaseAddress,
751 Entry->EndAddress - Entry->BaseAddress + 1,
752 Attributes
753 );
754 }
755
756 Link = Link->ForwardLink;
757 }
758
760 }
761}
762
771VOID
772EFIAPI
774 IN EFI_EVENT Event,
775 IN VOID *Context
776 )
777{
778 EFI_STATUS Status;
779 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
780 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
781 UINTN NoHandles;
782 EFI_HANDLE *HandleBuffer;
783 UINTN Index;
784
785 DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n"));
786 Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
787 if (EFI_ERROR (Status)) {
788 goto Done;
789 }
790
791 //
792 // Apply the memory protection policy on non-BScode/RTcode regions.
793 //
794 if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0) {
796 }
797
798 //
799 // Call notify function meant for Heap Guard.
800 //
802
803 if (mImageProtectionPolicy == 0) {
804 goto Done;
805 }
806
807 Status = gBS->LocateHandleBuffer (
809 &gEfiLoadedImageProtocolGuid,
810 NULL,
811 &NoHandles,
812 &HandleBuffer
813 );
814 if (EFI_ERROR (Status) && (NoHandles == 0)) {
815 goto Done;
816 }
817
818 for (Index = 0; Index < NoHandles; Index++) {
819 Status = gBS->HandleProtocol (
820 HandleBuffer[Index],
821 &gEfiLoadedImageProtocolGuid,
822 (VOID **)&LoadedImage
823 );
824 if (EFI_ERROR (Status)) {
825 continue;
826 }
827
828 Status = gBS->HandleProtocol (
829 HandleBuffer[Index],
830 &gEfiLoadedImageDevicePathProtocolGuid,
831 (VOID **)&LoadedImageDevicePath
832 );
833 if (EFI_ERROR (Status)) {
834 LoadedImageDevicePath = NULL;
835 }
836
837 ProtectUefiImage (LoadedImage, LoadedImageDevicePath);
838 }
839
840 FreePool (HandleBuffer);
841
842Done:
843 CoreCloseEvent (Event);
844}
845
849VOID
851 VOID
852 )
853{
854 EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage;
855 LIST_ENTRY *Link;
856
857 //
858 // We need remove the RT protection, because RT relocation need write code segment
859 // at SetVirtualAddressMap(). We cannot assume OS/Loader has taken over page table at that time.
860 //
861 // Firmware does not own page tables after ExitBootServices(), so the OS would
862 // have to relax protection of RT code pages across SetVirtualAddressMap(), or
863 // delay setting protections on RT code pages until after SetVirtualAddressMap().
864 // OS may set protection on RT based upon EFI_MEMORY_ATTRIBUTES_TABLE later.
865 //
866 if (mImageProtectionPolicy != 0) {
867 for (Link = gRuntime->ImageHead.ForwardLink; Link != &gRuntime->ImageHead; Link = Link->ForwardLink) {
868 RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
869 SetUefiImageMemoryAttributes ((UINT64)(UINTN)RuntimeImage->ImageBase, ALIGN_VALUE (RuntimeImage->ImageSize, EFI_PAGE_SIZE), 0);
870 }
871 }
872}
873
882VOID
883EFIAPI
885 EFI_EVENT Event,
886 VOID *Context
887 )
888{
889 EFI_STATUS Status;
891
892 DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): start\r\n"));
893 //
894 // Disable NULL pointer detection by enabling first 4K page
895 //
896 Status = CoreGetMemorySpaceDescriptor (0, &Desc);
897 ASSERT_EFI_ERROR (Status);
898
899 if ((Desc.Capabilities & EFI_MEMORY_RP) == 0) {
901 0,
902 EFI_PAGE_SIZE,
903 Desc.Capabilities | EFI_MEMORY_RP
904 );
905 ASSERT_EFI_ERROR (Status);
906 }
907
909 0,
910 EFI_PAGE_SIZE,
911 Desc.Attributes & ~EFI_MEMORY_RP
912 );
913 ASSERT_EFI_ERROR (Status);
914
915 //
916 // Page 0 might have be allocated to avoid misuses. Free it here anyway.
917 //
918 CoreFreePages (0, 1);
919
920 CoreCloseEvent (Event);
921 DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): end\r\n"));
922
923 return;
924}
925
929VOID
930EFIAPI
932 VOID
933 )
934{
935 EFI_STATUS Status;
936 EFI_EVENT Event;
937 EFI_EVENT EndOfDxeEvent;
938 VOID *Registration;
939
940 mImageProtectionPolicy = PcdGet32 (PcdImageProtectionPolicy);
941
942 InitializeListHead (&mProtectedImageRecordList);
943
944 //
945 // Sanity check the PcdDxeNxMemoryProtectionPolicy setting:
946 // - code regions should have no EFI_MEMORY_XP attribute
947 // - EfiConventionalMemory and EfiBootServicesData should use the
948 // same attribute
949 //
950 ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0);
951 ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0);
952 ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0);
953 ASSERT (
956 );
957
958 Status = CoreCreateEvent (
959 EVT_NOTIFY_SIGNAL,
960 TPL_CALLBACK,
962 NULL,
963 &Event
964 );
965 ASSERT_EFI_ERROR (Status);
966
967 //
968 // Register for protocol notifactions on this event
969 //
971 &gEfiCpuArchProtocolGuid,
972 Event,
973 &Registration
974 );
975 ASSERT_EFI_ERROR (Status);
976
977 //
978 // Register a callback to disable NULL pointer detection at EndOfDxe
979 //
980 if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7))
981 == (BIT0|BIT7))
982 {
983 Status = CoreCreateEventEx (
984 EVT_NOTIFY_SIGNAL,
985 TPL_NOTIFY,
987 NULL,
988 &gEfiEndOfDxeEventGroupGuid,
989 &EndOfDxeEvent
990 );
991 ASSERT_EFI_ERROR (Status);
992 }
993
994 return;
995}
996
1000STATIC
1001BOOLEAN
1003 VOID
1004 )
1005{
1006 BOOLEAN InSmm;
1007
1008 InSmm = FALSE;
1009 if (gSmmBase2 != NULL) {
1010 gSmmBase2->InSmm (gSmmBase2, &InSmm);
1011 }
1012
1013 return InSmm;
1014}
1015
1034EFIAPI
1036 IN EFI_MEMORY_TYPE OldType,
1037 IN EFI_MEMORY_TYPE NewType,
1038 IN EFI_PHYSICAL_ADDRESS Memory,
1039 IN UINT64 Length
1040 )
1041{
1042 UINT64 OldAttributes;
1043 UINT64 NewAttributes;
1044
1045 //
1046 // The policy configured in PcdDxeNxMemoryProtectionPolicy
1047 // does not apply to allocations performed in SMM mode.
1048 //
1049 if (IsInSmm ()) {
1050 return EFI_SUCCESS;
1051 }
1052
1053 //
1054 // If the CPU arch protocol is not installed yet, we cannot manage memory
1055 // permission attributes, and it is the job of the driver that installs this
1056 // protocol to set the permissions on existing allocations.
1057 //
1058 if (gCpu == NULL) {
1059 return EFI_SUCCESS;
1060 }
1061
1062 //
1063 // Check if a DXE memory protection policy has been configured
1064 //
1065 if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) == 0) {
1066 return EFI_SUCCESS;
1067 }
1068
1069 //
1070 // Don't overwrite Guard pages, which should be the first and/or last page,
1071 // if any.
1072 //
1073 if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL)) {
1074 if (IsGuardPage (Memory)) {
1075 Memory += EFI_PAGE_SIZE;
1076 Length -= EFI_PAGE_SIZE;
1077 if (Length == 0) {
1078 return EFI_SUCCESS;
1079 }
1080 }
1081
1082 if (IsGuardPage (Memory + Length - EFI_PAGE_SIZE)) {
1083 Length -= EFI_PAGE_SIZE;
1084 if (Length == 0) {
1085 return EFI_SUCCESS;
1086 }
1087 }
1088 }
1089
1090 //
1091 // Update the executable permissions according to the DXE memory
1092 // protection policy, but only if
1093 // - the policy is different between the old and the new type, or
1094 // - this is a newly added region (OldType == EfiMaxMemoryType)
1095 //
1096 NewAttributes = GetPermissionAttributeForMemoryType (NewType);
1097
1098 if (OldType != EfiMaxMemoryType) {
1099 OldAttributes = GetPermissionAttributeForMemoryType (OldType);
1100 if (OldAttributes == NewAttributes) {
1101 // policy is the same between OldType and NewType
1102 return EFI_SUCCESS;
1103 }
1104 } else if (NewAttributes == 0) {
1105 // newly added region of a type that does not require protection
1106 return EFI_SUCCESS;
1107 }
1108
1109 return gCpu->SetMemoryAttributes (gCpu, Memory, Length, NewAttributes);
1110}
UINT64 UINTN
#define MAX_ADDRESS
VOID *EFIAPI GetNextHob(IN UINT16 Type, IN CONST VOID *HobStart)
Definition: HobLib.c:103
VOID *EFIAPI GetHobList(VOID)
Definition: HobLib.c:76
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
BOOLEAN EFIAPI IsGuardPage(IN EFI_PHYSICAL_ADDRESS Address)
Definition: HeapGuard.c:461
BOOLEAN IsHeapGuardEnabled(UINT8 GuardType)
Definition: HeapGuard.c:674
VOID HeapGuardCpuArchProtocolNotify(VOID)
Definition: HeapGuard.c:1604
EFI_STATUS EFIAPI CoreFreePages(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NumberOfPages)
Definition: Page.c:1737
EFI_STATUS EFIAPI CoreGetMemorySpaceDescriptor(IN EFI_PHYSICAL_ADDRESS BaseAddress, OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor)
Definition: Gcd.c:1617
EFI_STATUS EFIAPI CoreLocateProtocol(IN EFI_GUID *Protocol, IN VOID *Registration OPTIONAL, OUT VOID **Interface)
Definition: Locate.c:575
VOID CoreAcquireGcdMemoryLock(VOID)
Definition: Gcd.c:266
EFI_STATUS EFIAPI CoreSetMemorySpaceCapabilities(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Capabilities)
Definition: Gcd.c:1711
EFI_STATUS EFIAPI CoreSetMemorySpaceAttributes(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
Definition: Gcd.c:1680
EFI_STATUS EFIAPI CoreRegisterProtocolNotify(IN EFI_GUID *Protocol, IN EFI_EVENT Event, OUT VOID **Registration)
Definition: Notify.c:99
EFI_STATUS EFIAPI CoreCreateEventEx(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN CONST VOID *NotifyContext OPTIONAL, IN CONST EFI_GUID *EventGroup OPTIONAL, OUT EFI_EVENT *Event)
Definition: Event.c:312
EFI_STATUS EFIAPI CoreCloseEvent(IN EFI_EVENT UserEvent)
Definition: Event.c:700
VOID CoreReleaseGcdMemoryLock(VOID)
Definition: Gcd.c:278
EFI_STATUS EFIAPI CoreCreateEvent(IN UINT32 Type, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *Event)
Definition: Event.c:279
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID EFIAPI DeleteImagePropertiesRecord(IN IMAGE_PROPERTIES_RECORD *ImageRecord)
EFI_STATUS EFIAPI CreateImagePropertiesRecord(IN CONST VOID *ImageBase, IN CONST UINT64 ImageSize, IN CONST UINT32 *Alignment OPTIONAL, OUT IMAGE_PROPERTIES_RECORD *ImageRecord)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define BASE_CR(Record, TYPE, Field)
Definition: Base.h:891
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
UINT32 GetUefiImageProtectionPolicy(IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath)
STATIC BOOLEAN IsInSmm(VOID)
VOID MemoryProtectionExitBootServicesCallback(VOID)
VOID SetUefiImageMemoryAttributes(IN UINT64 BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
VOID ProtectUefiImage(IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath)
UINT32 GetImageType(IN CONST EFI_DEVICE_PATH_PROTOCOL *File)
STATIC VOID MergeMemoryMapForProtectionPolicy(IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN OUT UINTN *MemoryMapSize, IN UINTN DescriptorSize)
VOID SetUefiImageProtectionAttributes(IN IMAGE_PROPERTIES_RECORD *ImageRecord)
STATIC VOID InitializeDxeNxMemoryProtectionPolicy(VOID)
VOID EFIAPI DisableNullDetectionAtTheEndOfDxe(EFI_EVENT Event, VOID *Context)
UINT32 GetProtectionPolicyFromImageType(IN UINT32 ImageType)
EFI_STATUS EFIAPI ApplyMemoryProtectionPolicy(IN EFI_MEMORY_TYPE OldType, IN EFI_MEMORY_TYPE NewType, IN EFI_PHYSICAL_ADDRESS Memory, IN UINT64 Length)
STATIC UINT32 GetMemoryProtectionSectionAlignment(IN EFI_MEMORY_TYPE MemoryType)
VOID EFIAPI CoreInitializeMemoryProtection(VOID)
STATIC VOID SortMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN UINTN MemoryMapSize, IN UINTN DescriptorSize)
VOID EFIAPI MemoryProtectionCpuArchProtocolNotify(IN EFI_EVENT Event, IN VOID *Context)
VOID UnprotectUefiImage(IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath)
STATIC UINT64 GetPermissionAttributeForMemoryType(IN EFI_MEMORY_TYPE MemoryType)
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
@ EfiGcdMemoryTypeReserved
Definition: PiDxeCis.h:32
BOOLEAN EFIAPI InSmm(VOID)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_MEMORY_TYPE
@ EfiBootServicesData
@ EfiReservedMemoryType
@ EfiBootServicesCode
@ EfiConventionalMemory
@ EfiACPIMemoryNVS
@ EfiACPIReclaimMemory
@ EfiLoaderCode
@ EfiRuntimeServicesCode
@ EfiRuntimeServicesData
@ ByProtocol
Definition: UefiSpec.h:1518
EFI_LIST_ENTRY ImageHead
A list of type EFI_RUNTIME_IMAGE_ENTRY.
Definition: Runtime.h:108
EFI_PHYSICAL_ADDRESS MemoryBaseAddress
Definition: PiHob.h:119
EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor
Definition: PiHob.h:153
EFI_PHYSICAL_ADDRESS PhysicalStart
Definition: UefiSpec.h:155