OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
CustomSlide.c
Go to the documentation of this file.
1
16#include "BootCompatInternal.h"
17
18#include <Guid/AppleVariable.h>
19#include <Guid/OcVariable.h>
22
23#include <Library/BaseLib.h>
24#include <Library/BaseMemoryLib.h>
25#include <Library/DebugLib.h>
27#include <Library/OcCryptoLib.h>
29#include <Library/OcMachoLib.h>
30#include <Library/OcMemoryLib.h>
31#include <Library/OcMiscLib.h>
32#include <Library/OcRngLib.h>
33#include <Library/OcStringLib.h>
34#include <Library/PrintLib.h>
35#include <Library/UefiBootServicesTableLib.h>
36#include <Library/UefiLib.h>
37#include <Library/UefiRuntimeServicesTableLib.h>
38
49STATIC
50VOID
52 IN UINTN EstimatedKernelArea,
53 IN BOOLEAN HasSandyOrIvy,
54 IN UINT8 Slide,
55 OUT UINTN *StartAddr,
56 OUT UINTN *EndAddr
57 )
58{
59 *StartAddr = Slide * SLIDE_GRANULARITY + KERNEL_BASE_PADDR;
60
61 //
62 // Skip ranges used by Intel HD 2000/3000.
63 //
64 if ((Slide >= SLIDE_ERRATA_NUM) && HasSandyOrIvy) {
65 *StartAddr += SLIDE_ERRATA_SKIP_RANGE;
66 }
67
68 *EndAddr = *StartAddr + EstimatedKernelArea;
69}
70
76STATIC
77UINT8
79 IN SLIDE_SUPPORT_STATE *SlideSupport
80 )
81{
82 UINT32 Slide;
83
84 //
85 // Handle 0 slide case.
86 //
87 if (SlideSupport->ValidSlideCount == 1) {
88 return SlideSupport->ValidSlides[0];
89 }
90
91 do {
92 DivU64x32Remainder (GetPseudoRandomNumber64 (), SlideSupport->ValidSlideCount, &Slide);
93 } while (SlideSupport->ValidSlides[Slide] == 0);
94
95 return SlideSupport->ValidSlides[Slide];
96}
97
108STATIC
109BOOLEAN
111 IN OUT SLIDE_SUPPORT_STATE *SlideSupport,
112 IN UINT8 FallbackSlide,
113 IN UINT64 MaxAvailableSize
114 )
115{
116 UINTN Index;
117 UINTN NumEntries;
118 CHAR8 SlideList[256];
119 CHAR8 Temp[32];
120
121 //
122 // All slides are available.
123 //
124 if (SlideSupport->ValidSlideCount == TOTAL_SLIDE_NUM) {
125 DEBUG ((
126 DEBUG_INFO,
127 "OCABC: All slides are usable! You can disable ProvideCustomSlide!\n"
128 ));
129 return FALSE;
130 }
131
132 //
133 // No slides are available, fallback to largest.
134 //
135 if (SlideSupport->ValidSlideCount == 0) {
136 DEBUG ((
137 DEBUG_INFO,
138 "OCABC: No slide values are usable! Falling back to %u with 0x%08LX bytes!\n",
139 (UINT32)FallbackSlide,
140 MaxAvailableSize
141 ));
142 SlideSupport->ValidSlides[SlideSupport->ValidSlideCount++] = (UINT8)FallbackSlide;
143 return TRUE;
144 }
145
146 //
147 // Not all slides are available and thus we have to pass a custom slide
148 // value through boot-args to boot reliably.
149 //
150 // Pretty-print valid slides as ranges.
151 // For example, 1, 2, 3, 4, 5 will become 1-5.
152 //
153 DEBUG ((
154 DEBUG_INFO,
155 "OCABC: Only %u/%u slide values are usable!\n",
156 (UINT32)SlideSupport->ValidSlideCount,
157 (UINT32)TOTAL_SLIDE_NUM
158 ));
159
160 SlideList[0] = '\0';
161
162 NumEntries = 0;
163 for (Index = 0; Index <= SlideSupport->ValidSlideCount; ++Index) {
164 if (Index == 0) {
165 AsciiSPrint (
166 Temp,
167 sizeof (Temp),
168 "Valid slides - %d",
169 SlideSupport->ValidSlides[Index]
170 );
171 AsciiStrCatS (SlideList, sizeof (SlideList), Temp);
172 } else if ( (Index == SlideSupport->ValidSlideCount)
173 || (SlideSupport->ValidSlides[Index - 1] + 1 != SlideSupport->ValidSlides[Index]))
174 {
175 if (NumEntries == 1) {
176 AsciiSPrint (
177 Temp,
178 sizeof (Temp),
179 ", %d",
180 SlideSupport->ValidSlides[Index - 1]
181 );
182 AsciiStrCatS (SlideList, sizeof (SlideList), Temp);
183 } else if (NumEntries > 1) {
184 AsciiSPrint (
185 Temp,
186 sizeof (Temp),
187 "-%d",
188 SlideSupport->ValidSlides[Index - 1]
189 );
190 AsciiStrCatS (SlideList, sizeof (SlideList), Temp);
191 }
192
193 if (Index != SlideSupport->ValidSlideCount) {
194 AsciiSPrint (
195 Temp,
196 sizeof (Temp),
197 ", %d",
198 SlideSupport->ValidSlides[Index]
199 );
200 AsciiStrCatS (SlideList, sizeof (SlideList), Temp);
201 }
202
203 NumEntries = 0;
204 } else {
205 NumEntries++;
206 }
207 }
208
209 DEBUG ((DEBUG_INFO, "OCABC: %a\n", SlideList));
210
211 return TRUE;
212}
213
225STATIC
226BOOLEAN
228 IN OUT SLIDE_SUPPORT_STATE *SlideSupport,
229 IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL,
230 IN OC_MEMORY_FILTER FilterMap OPTIONAL,
231 IN VOID *FilterMapContext OPTIONAL,
232 IN BOOLEAN HasSandyOrIvy
233 )
234{
235 EFI_PHYSICAL_ADDRESS AllocatedMapPages;
236 UINTN MemoryMapSize;
237 EFI_MEMORY_DESCRIPTOR *MemoryMap;
238 EFI_MEMORY_DESCRIPTOR *Desc;
239 UINTN MapKey;
240 EFI_STATUS Status;
241 UINTN DescriptorSize;
242 UINT32 DescriptorVersion;
243 UINTN Index;
244 UINTN Slide;
245 UINTN NumEntries;
246 UINT64 MaxAvailableSize;
247 UINT8 FallbackSlide;
248 BOOLEAN Supported;
249 UINTN StartAddr;
250 UINTN EndAddr;
251 EFI_PHYSICAL_ADDRESS DescEndAddr;
252 UINT64 AvailableSize;
253
254 MaxAvailableSize = 0;
255 FallbackSlide = 0;
256
257 if (SlideSupport->HasMemoryMapAnalysis) {
258 return SlideSupport->ValidSlideCount > 0
259 && SlideSupport->ValidSlideCount < TOTAL_SLIDE_NUM;
260 }
261
262 AllocatedMapPages = BASE_4GB;
264 &MemoryMapSize,
265 &MemoryMap,
266 &MapKey,
267 &DescriptorSize,
268 &DescriptorVersion,
269 GetMemoryMap,
270 &AllocatedMapPages
271 );
272
273 if (EFI_ERROR (Status)) {
274 DEBUG ((DEBUG_WARN, "OCABC: Failed to obtain memory map for KASLR - %r\n", Status));
275 return FALSE;
276 }
277
278 if (FilterMap != NULL) {
279 FilterMap (FilterMapContext, MemoryMapSize, MemoryMap, DescriptorSize);
280 }
281
282 SlideSupport->HasSandyOrIvy = HasSandyOrIvy;
283
284 SlideSupport->EstimatedKernelArea = (UINTN)EFI_PAGES_TO_SIZE (
285 OcCountRuntimePages (MemoryMapSize, MemoryMap, DescriptorSize, NULL)
287
288 //
289 // At this point we have a memory map that we could use to
290 // determine what slide values are allowed.
291 //
292 NumEntries = MemoryMapSize / DescriptorSize;
293
294 //
295 // Reset valid slides to zero and find actually working ones.
296 //
297 SlideSupport->ValidSlideCount = 0;
298
299 for (Slide = 0; Slide < TOTAL_SLIDE_NUM; ++Slide) {
300 Desc = MemoryMap;
301 Supported = TRUE;
302
304 SlideSupport->EstimatedKernelArea,
305 SlideSupport->HasSandyOrIvy,
306 (UINT8)Slide,
307 &StartAddr,
308 &EndAddr
309 );
310
311 AvailableSize = 0;
312
313 for (Index = 0; Index < NumEntries; ++Index) {
314 if (Desc->NumberOfPages == 0) {
315 continue;
316 }
317
318 DescEndAddr = LAST_DESCRIPTOR_ADDR (Desc) + 1;
319
320 if ((Desc->PhysicalStart < EndAddr) && (DescEndAddr > StartAddr)) {
321 //
322 // The memory overlaps with the slide region.
323 //
324 if (Desc->Type != EfiConventionalMemory) {
325 //
326 // The memory is unusable atm.
327 //
328 Supported = FALSE;
329 break;
330 } else {
331 //
332 // The memory will be available for the kernel.
333 //
334 AvailableSize += EFI_PAGES_TO_SIZE (Desc->NumberOfPages);
335
336 if (Desc->PhysicalStart < StartAddr) {
337 //
338 // The region starts before the slide region.
339 // Subtract the memory that is located before the slide region.
340 //
341 AvailableSize -= (StartAddr - Desc->PhysicalStart);
342 }
343
344 if (DescEndAddr > EndAddr) {
345 //
346 // The region ends after the slide region.
347 // Subtract the memory that is located after the slide region.
348 //
349 AvailableSize -= (DescEndAddr - EndAddr);
350 }
351 }
352 }
353
354 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
355 }
356
357 if (AvailableSize > MaxAvailableSize) {
358 MaxAvailableSize = AvailableSize;
359 FallbackSlide = (UINT8)Slide;
360 }
361
362 //
363 // Stop evalutating slides after exceeding ProvideMaxSlide, may break when
364 // no slides are available.
365 //
366 if ((SlideSupport->ProvideMaxSlide > 0) && (Slide > SlideSupport->ProvideMaxSlide)) {
367 break;
368 }
369
370 if ((StartAddr + AvailableSize) != EndAddr) {
371 //
372 // The slide region is not continuous.
373 //
374 Supported = FALSE;
375 }
376
377 if (Supported) {
378 SlideSupport->ValidSlides[SlideSupport->ValidSlideCount++] = (UINT8)Slide;
379 }
380 }
381
382 //
383 // Okay, we are done.
384 //
385
386 SlideSupport->HasMemoryMapAnalysis = TRUE;
387
388 gBS->FreePages (
389 (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryMap,
390 (UINTN)AllocatedMapPages
391 );
392
394 SlideSupport,
395 FallbackSlide,
396 MaxAvailableSize
397 );
398}
399
414STATIC
415EFI_STATUS
417 IN OUT SLIDE_SUPPORT_STATE *SlideSupport,
418 IN EFI_GET_VARIABLE GetVariable,
419 IN CHAR16 *VariableName,
420 IN EFI_GUID *VendorGuid,
421 OUT UINT32 *Attributes OPTIONAL,
422 IN OUT UINTN *DataSize,
423 OUT VOID *Data
424 )
425{
426 EFI_STATUS Status;
427 UINT32 *Config;
428
429 //
430 // If we were asked for the size, just return it right away.
431 //
432 if ((Data == NULL) || (*DataSize < sizeof (UINT32))) {
433 *DataSize = sizeof (UINT32);
434 return EFI_BUFFER_TOO_SMALL;
435 }
436
437 Config = (UINT32 *)Data;
438
439 //
440 // Otherwise call the original function.
441 //
442 Status = GetVariable (VariableName, VendorGuid, Attributes, DataSize, Data);
443 if (EFI_ERROR (Status)) {
444 DEBUG ((DEBUG_INFO, "OCABC: GetVariable csr-active-config - %r\n", Status));
445
446 *Config = 0;
447 Status = EFI_SUCCESS;
448 if (Attributes != NULL) {
449 *Attributes =
450 EFI_VARIABLE_BOOTSERVICE_ACCESS |
451 EFI_VARIABLE_RUNTIME_ACCESS |
452 EFI_VARIABLE_NON_VOLATILE;
453 }
454 }
455
456 //
457 // We must unrestrict NVRAM from SIP or slide=X will not be supported.
458 //
459 SlideSupport->CsrActiveConfig = *Config;
460 SlideSupport->HasCsrActiveConfig = TRUE;
462
463 return Status;
464}
465
480STATIC
481EFI_STATUS
483 IN OUT SLIDE_SUPPORT_STATE *SlideSupport,
484 IN EFI_GET_VARIABLE GetVariable,
485 IN CHAR16 *VariableName,
486 IN EFI_GUID *VendorGuid,
487 OUT UINT32 *Attributes OPTIONAL,
488 IN OUT UINTN *DataSize,
489 OUT VOID *Data
490 )
491{
492 EFI_STATUS Status;
493 UINTN StoredBootArgsSize;
494 UINT8 Slide;
495 CHAR8 SlideArgument[10];
496 UINTN SlideArgumentLength;
497
498 StoredBootArgsSize = BOOT_LINE_LENGTH;
499 SlideArgumentLength = ARRAY_SIZE (SlideArgument) - 1;
500
501 if (!SlideSupport->HasBootArgs) {
502 Slide = GenerateSlideValue (SlideSupport);
503
504 //
505 // boot-args normally arrives non-null terminated.
506 //
507 Status = GetVariable (
508 VariableName,
509 VendorGuid,
510 Attributes,
511 &StoredBootArgsSize,
512 SlideSupport->BootArgs
513 );
514 if (EFI_ERROR (Status)) {
515 SlideSupport->BootArgs[0] = '\0';
516 }
517
518 //
519 // Note, the point is to always pass 3 characters to avoid side attacks on value length.
520 // boot.efi always reads in decimal, so 008 and 8 are equivalent.
521 //
522 AsciiSPrint (SlideArgument, ARRAY_SIZE (SlideArgument), "slide=%-03d", Slide);
523
524 if (!OcAppendArgumentToCmd (NULL, SlideSupport->BootArgs, SlideArgument, SlideArgumentLength)) {
525 //
526 // Broken boot-args, try to overwrite.
527 //
528 AsciiStrnCpyS (
529 SlideSupport->BootArgs,
530 SlideArgumentLength + 1,
531 SlideArgument,
532 SlideArgumentLength + 1
533 );
534 }
535
536 SlideSupport->BootArgsSize = AsciiStrLen (SlideSupport->BootArgs);
537 SlideSupport->HasBootArgs = TRUE;
538 }
539
540 if (Attributes) {
541 *Attributes =
542 EFI_VARIABLE_BOOTSERVICE_ACCESS |
543 EFI_VARIABLE_RUNTIME_ACCESS |
544 EFI_VARIABLE_NON_VOLATILE;
545 }
546
547 if ((*DataSize >= SlideSupport->BootArgsSize) && (Data != NULL)) {
548 CopyMem (
549 Data,
550 SlideSupport->BootArgs,
551 SlideSupport->BootArgsSize
552 );
553 Status = EFI_SUCCESS;
554 } else {
555 Status = EFI_BUFFER_TOO_SMALL;
556 }
557
558 *DataSize = SlideSupport->BootArgsSize;
559
560 return Status;
561}
562
570STATIC
571VOID
573 IN OUT SLIDE_SUPPORT_STATE *SlideSupport,
574 IN OUT OC_BOOT_ARGUMENTS *BootArgs
575 )
576{
577 EFI_STATUS Status;
578 DTEntry Chosen;
579 CHAR8 *ArgsStr;
580 UINT32 ArgsSize;
581
582 //
583 // First, there is a BootArgs entry for XNU.
584 //
585 OcRemoveArgumentFromCmd (BootArgs->CommandLine, "slide=");
586
587 //
588 // Second, there is a DT entry.
589 //
590 DTInit ((VOID *)(UINTN)(*BootArgs->DeviceTreeP), BootArgs->DeviceTreeLength);
591 Status = DTLookupEntry (NULL, "/chosen", &Chosen);
592 if (!EFI_ERROR (Status)) {
593 Status = DTGetProperty (Chosen, "boot-args", (VOID **)&ArgsStr, &ArgsSize);
594 if (!EFI_ERROR (Status) && (ArgsSize > 0)) {
595 OcRemoveArgumentFromCmd (ArgsStr, "slide=");
596 }
597 }
598
599 //
600 // Third, clean the boot args just in case.
601 //
602 SlideSupport->ValidSlideCount = 0;
603 SlideSupport->BootArgsSize = 0;
604 SecureZeroMem (SlideSupport->ValidSlides, sizeof (SlideSupport->ValidSlides));
605 SecureZeroMem (SlideSupport->BootArgs, sizeof (SlideSupport->BootArgs));
606}
607
608VOID
610 IN OUT UINT8 *ImageBase,
611 IN UINTN ImageSize
612 )
613{
614 //
615 // boot.efi performs the following check:
616 // if (State & (BOOT_MODE_SAFE | BOOT_MODE_ASLR)) == (BOOT_MODE_SAFE | BOOT_MODE_ASLR)) {
617 // * Disable KASLR *
618 // }
619 // We do not care about the asm it will use for it, but we could assume that the constants
620 // will be used twice and their location will be very close to each other.
621 //
622 // BOOT_MODE_SAFE | BOOT_MODE_ASLR constant is 0x4001 in hex.
623 // It has not changed since its appearance, so is most likely safe to look for.
624 // Furthermore, since boot.efi state mask uses higher bits, it is safe to assume that
625 // the comparison will be at least 32-bit.
626 //
627 //
628 // The new way patch is a workaround for 10.13.5 and newer, where the code got finally changed.
629 // if (State & BOOT_MODE_SAFE) {
630 // ReportFeature(FEATURE_BOOT_MODE_SAFE);
631 // if (State & BOOT_MODE_ASLR) {
632 // * Disable KASLR *
633 // }
634 // }
635 //
636 // The even newer workaround for 11.0 a newer is to patch the test.
637 // if (State & BOOT_MODE_SAFE) {
638 // * Do roughly nothing *
639 // } else {
640 // * Setup KASLR *
641 //
642
643 //
644 // This is a reasonable maximum distance to expect between the instructions.
645 //
646 STATIC CONST UINTN MaxDist = 0x10;
647 STATIC CONST UINT8 SearchSeqNew[] = { 0xF6, 0xC4, 0x40, 0x75 };
648 STATIC CONST UINT8 SearchSeqNew2[] = { 0x0F, 0xBA, 0xE0, 0x0E, 0x72 };
649 STATIC CONST UINT8 SearchSeqSur[] = { 0xF6, 0xC1, 0x01, 0x75 };
650 STATIC CONST UINT8 SearchSeqSur2[] = { 0xF6, 0xC1, 0x01, 0x74 };
651 STATIC CONST UINT8 SearchSeq[] = { 0x01, 0x40, 0x00, 0x00 };
652
653 UINT8 *StartOff;
654 UINT8 *EndOff;
655 UINTN FirstOff;
656 UINTN SecondOff;
657 UINTN SearchSeqNewSize;
658 BOOLEAN NewWay;
659 BOOLEAN IsSur;
660 UINT32 SurOffset;
661
662 StartOff = ImageBase;
663 EndOff = StartOff + ImageSize - sizeof (SearchSeq) - MaxDist;
664
665 //
666 // Rebranding started with macOS 11. All the ones before had Mac OS X or none.
667 //
668 SurOffset = 0;
669 IsSur = FindPattern (
670 (CONST UINT8 *)"macOS ",
671 NULL,
672 L_STR_LEN ("macOS "),
673 ImageBase,
674 (UINT32)ImageSize,
675 &SurOffset
676 );
677
678 if (IsSur) {
679 for (FirstOff = 0; StartOff + FirstOff <= EndOff; ++FirstOff) {
680 if (CompareMem (StartOff + FirstOff, SearchSeqSur, sizeof (SearchSeqSur)) == 0) {
681 DEBUG ((DEBUG_INFO, "OCABC: Patching safe mode sur-1 at off %X\n", (UINT32)FirstOff));
682 SetMem (StartOff + FirstOff, sizeof (SearchSeqSur) + 1, 0x90);
683 return;
684 }
685
686 if (CompareMem (StartOff + FirstOff, SearchSeqSur2, sizeof (SearchSeqSur2)) == 0) {
687 DEBUG ((DEBUG_INFO, "OCABC: Patching safe mode sur-2 at off %X\n", (UINT32)FirstOff));
688 *(StartOff + FirstOff + 3) = 0xEB;
689 return;
690 }
691 }
692
693 DEBUG ((DEBUG_INFO, "OCABC: Failed to find safe mode sur sequence\n"));
694 return;
695 }
696
697 FirstOff = 0;
698 SecondOff = 0;
699
700 do {
701 NewWay = FALSE;
702
703 while (StartOff + FirstOff <= EndOff) {
704 if ( (StartOff + FirstOff <= EndOff - 1)
705 && (CompareMem (StartOff + FirstOff, SearchSeqNew2, sizeof (SearchSeqNew2)) == 0))
706 {
707 SearchSeqNewSize = sizeof (SearchSeqNew2);
708 NewWay = TRUE;
709 break;
710 }
711
712 if (CompareMem (StartOff + FirstOff, SearchSeqNew, sizeof (SearchSeqNew)) == 0) {
713 SearchSeqNewSize = sizeof (SearchSeqNew);
714 NewWay = TRUE;
715 break;
716 }
717
718 if (CompareMem (StartOff + FirstOff, SearchSeq, sizeof (SearchSeq)) == 0) {
719 break;
720 }
721
722 FirstOff++;
723 }
724
725 if (StartOff + FirstOff > EndOff) {
726 DEBUG ((DEBUG_INFO, "OCABC: Failed to find safe mode sequence\n"));
727 return;
728 }
729
730 if (NewWay) {
731 //
732 // Here we just patch the comparison code and the check by straight nopping.
733 //
734 DEBUG ((DEBUG_INFO, "OCABC: Patching safe mode new at off %X\n", (UINT32)FirstOff));
735 SetMem (StartOff + FirstOff, SearchSeqNewSize + 1, 0x90);
736 return;
737 }
738
739 DEBUG ((DEBUG_INFO, "OCABC: Found safe mode legacy p1 at off %X\n", (UINT32)FirstOff));
740
741 SecondOff = FirstOff + sizeof (SearchSeq);
742
743 while (
744 StartOff + SecondOff <= EndOff && FirstOff + MaxDist >= SecondOff &&
745 CompareMem (StartOff + SecondOff, SearchSeq, sizeof (SearchSeq)))
746 {
747 SecondOff++;
748 }
749
750 if (FirstOff + MaxDist < SecondOff) {
751 DEBUG ((DEBUG_INFO, "OCABC: Trying safe mode next legacy match\n"));
752 SecondOff = 0;
753 FirstOff += sizeof (SearchSeq);
754 continue;
755 }
756
757 DEBUG ((DEBUG_INFO, "OCABC: Found safe mode legacy p2 at off %X\n", (UINT32)SecondOff));
758 } while (SecondOff == 0);
759
760 if (SecondOff != 0) {
761 //
762 // Here we use 0xFFFFFFFF constant as a replacement value.
763 // Since the state values are contradictive (e.g. safe & single at the same time)
764 // We are allowed to use this instead of to simulate if (false).
765 //
766 DEBUG ((DEBUG_INFO, "OCABC: Patching safe mode legacy\n"));
767 SetMem (StartOff + FirstOff, sizeof (SearchSeq), 0xFF);
768 SetMem (StartOff + SecondOff, sizeof (SearchSeq), 0xFF);
769 }
770}
771
772EFI_STATUS
774 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
775 IN EFI_GET_VARIABLE GetVariable,
776 IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL,
777 IN OC_MEMORY_FILTER FilterMap OPTIONAL,
778 IN VOID *FilterMapContext OPTIONAL,
779 IN CHAR16 *VariableName,
780 IN EFI_GUID *VendorGuid,
781 OUT UINT32 *Attributes OPTIONAL,
782 IN OUT UINTN *DataSize,
783 OUT VOID *Data
784 )
785{
786 BootCompat->SlideSupport.ProvideMaxSlide = BootCompat->Settings.ProvideMaxSlide;
787
788 if ( (VariableName != NULL) && (VendorGuid != NULL) && (DataSize != NULL)
789 && CompareGuid (VendorGuid, &gAppleBootVariableGuid))
790 {
791 if (StrCmp (VariableName, L"csr-active-config") == 0) {
792 //
793 // We override csr-active-config with CSR_ALLOW_UNRESTRICTED_NVRAM bit set
794 // to allow one to pass a custom slide value even when SIP is on.
795 // This original value of csr-active-config is returned to OS at XNU boot.
796 // This allows SIP to be fully enabled in the operating system.
797 //
799 &BootCompat->SlideSupport,
800 GetVariable,
801 VariableName,
802 VendorGuid,
803 Attributes,
804 DataSize,
805 Data
806 );
807 } else if ( (StrCmp (VariableName, L"boot-args") == 0)
808 && (!BootCompat->ServiceState.AppleCustomSlide || BootCompat->Settings.AllowRelocationBlock)
810 &BootCompat->SlideSupport,
811 GetMemoryMap,
812 FilterMap,
813 FilterMapContext,
814 (BootCompat->CpuInfo->CpuGeneration == OcCpuGenerationSandyBridge)
815 || (BootCompat->CpuInfo->CpuGeneration == OcCpuGenerationIvyBridge)
816 ))
817 {
818 //
819 // When we cannot allow some KASLR values due to used address we generate
820 // a random slide value among the valid options, which we we pass via boot-args.
821 // See ShouldUseCustomSlideOffset for more details.
822 //
823 // We delay memory map analysis as much as we can, in case boot.efi or anything else allocates
824 // stuff with gBS->AllocatePool and it overlaps with the kernel area.
825 // Overriding AllocatePool with a custom allocator does not really improve the situation,
826 // because on older boards allocated memory above BASE_4GB causes instant reboots, and
827 // on the only (so far) problematic X99 and X299 we have no free region for our pool anyway.
828 // In any case, the current APTIOFIX_SPECULATED_KERNEL_SIZE value appears to work reliably.
829 //
830 // Note, when relocation block support is enabled, we always do the slide analysis
831 // (even when slide=0 is requested) to understand whether we need it or not at a later stage.
832 //
833 return GetVariableBootArgs (
834 &BootCompat->SlideSupport,
835 GetVariable,
836 VariableName,
837 VendorGuid,
838 Attributes,
839 DataSize,
840 Data
841 );
842 }
843 }
844
845 return GetVariable (VariableName, VendorGuid, Attributes, DataSize, Data);
846}
847
848VOID
850 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
851 IN OUT OC_BOOT_ARGUMENTS *BootArgs
852 )
853{
854 SLIDE_SUPPORT_STATE *SlideSupport;
855
856 SlideSupport = &BootCompat->SlideSupport;
857
858 //
859 // Restore csr-active-config to a value it was before our slide=X alteration.
860 //
861 if ((BootArgs->CsrActiveConfig != NULL) && SlideSupport->HasCsrActiveConfig) {
862 //
863 // Never enable more bits than EfiBoot actually allowed.
864 // On public builds EfiBoot will clear the CSR_ALLOW_APPLE_INTERNAL
865 // bit, and we must not re-enable it.
866 //
867 *BootArgs->CsrActiveConfig &= SlideSupport->CsrActiveConfig;
868 }
869
870 //
871 // Having slide=X values visible in the operating system defeats the purpose of KASLR.
872 // Since our custom implementation works by passing random KASLR slide via boot-args,
873 // this is especially important.
874 //
875 HideSlideFromOs (SlideSupport, BootArgs);
876}
877
878UINTN
880 IN OUT BOOT_COMPAT_CONTEXT *BootCompat
881 )
882{
883 SLIDE_SUPPORT_STATE *SlideSupport;
884
885 SlideSupport = &BootCompat->SlideSupport;
886
887 //
888 // When we could not have performed the analysis we have nothing to offer.
889 //
890 if (!SlideSupport->HasMemoryMapAnalysis) {
891 return 0;
892 }
893
894 //
895 // When we have no slides available we assume 0 is also unavailable.
896 //
897 if (SlideSupport->ValidSlideCount == 0) {
898 return BootCompat->SlideSupport.EstimatedKernelArea;
899 }
900
901 //
902 // If the first slide is not zero, then zero is unavailable.
903 //
904 if (SlideSupport->ValidSlides[0] != 0) {
905 return BootCompat->SlideSupport.EstimatedKernelArea;
906 }
907
908 return 0;
909}
#define BOOT_LINE_LENGTH
#define CSR_ALLOW_UNRESTRICTED_NVRAM
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
EFI_GUID gAppleBootVariableGuid
#define SLIDE_ERRATA_SKIP_RANGE
#define SLIDE_GRANULARITY
#define KERNEL_BASE_PADDR
#define SLIDE_ERRATA_NUM
#define TOTAL_SLIDE_NUM
#define ESTIMATED_KERNEL_SIZE
VOID AppleSlideRestore(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN OUT OC_BOOT_ARGUMENTS *BootArgs)
STATIC EFI_STATUS GetVariableCsrActiveConfig(IN OUT SLIDE_SUPPORT_STATE *SlideSupport, IN EFI_GET_VARIABLE GetVariable, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data)
STATIC UINT8 GenerateSlideValue(IN SLIDE_SUPPORT_STATE *SlideSupport)
Definition CustomSlide.c:78
VOID AppleSlideUnlockForSafeMode(IN OUT UINT8 *ImageBase, IN UINTN ImageSize)
STATIC VOID HideSlideFromOs(IN OUT SLIDE_SUPPORT_STATE *SlideSupport, IN OUT OC_BOOT_ARGUMENTS *BootArgs)
STATIC VOID GetSlideRangeForValue(IN UINTN EstimatedKernelArea, IN BOOLEAN HasSandyOrIvy, IN UINT8 Slide, OUT UINTN *StartAddr, OUT UINTN *EndAddr)
Definition CustomSlide.c:51
UINTN AppleSlideGetRelocationSize(IN OUT BOOT_COMPAT_CONTEXT *BootCompat)
STATIC BOOLEAN ShouldUseCustomSlideOffset(IN OUT SLIDE_SUPPORT_STATE *SlideSupport, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL, IN OC_MEMORY_FILTER FilterMap OPTIONAL, IN VOID *FilterMapContext OPTIONAL, IN BOOLEAN HasSandyOrIvy)
STATIC BOOLEAN ShouldUseCustomSlideOffsetDecision(IN OUT SLIDE_SUPPORT_STATE *SlideSupport, IN UINT8 FallbackSlide, IN UINT64 MaxAvailableSize)
EFI_STATUS AppleSlideGetVariable(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN EFI_GET_VARIABLE GetVariable, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL, IN OC_MEMORY_FILTER FilterMap OPTIONAL, IN VOID *FilterMapContext OPTIONAL, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data)
STATIC EFI_STATUS GetVariableBootArgs(IN OUT SLIDE_SUPPORT_STATE *SlideSupport, IN EFI_GET_VARIABLE GetVariable, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data)
VOID OcRemoveArgumentFromCmd(IN OUT CHAR8 *CommandLine, IN CONST CHAR8 *Argument)
BOOLEAN OcAppendArgumentToCmd(IN OUT OC_PICKER_CONTEXT *Context OPTIONAL, IN OUT CHAR8 *CommandLine, IN CONST CHAR8 *Argument, IN CONST UINTN ArgumentLength)
EFI_BOOT_SERVICES * gBS
@ OcCpuGenerationIvyBridge
Definition OcCpuLib.h:47
@ OcCpuGenerationSandyBridge
Definition OcCpuLib.h:45
VOID * SecureZeroMem(OUT VOID *Buffer, IN UINTN Length)
Definition SecureMem.c:73
EFI_STATUS DTLookupEntry(IN CONST DTEntry SearchPoint, IN CONST CHAR8 *PathName, IN DTEntry *FoundEntry)
VOID DTInit(IN VOID *Base, IN UINT32 *Length)
EFI_STATUS DTGetProperty(IN CONST DTEntry Entry, IN CHAR8 *PropertyName, IN VOID **PropertyValue, IN UINT32 *PropertySize)
EFI_STATUS OcGetCurrentMemoryMapAlloc(OUT UINTN *MemoryMapSize, OUT EFI_MEMORY_DESCRIPTOR **MemoryMap, OUT UINTN *MapKey, OUT UINTN *DescriptorSize, OUT UINT32 *DescriptorVersion, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL, IN OUT EFI_PHYSICAL_ADDRESS *TopMemory OPTIONAL)
Definition MemoryMap.c:201
#define LAST_DESCRIPTOR_ADDR(Desc)
Definition OcMemoryLib.h:32
UINT64 OcCountRuntimePages(IN UINTN MemoryMapSize, IN EFI_MEMORY_DESCRIPTOR *MemoryMap, IN UINTN DescriptorSize, OUT UINTN *DescriptorCount OPTIONAL)
VOID(* OC_MEMORY_FILTER)(IN VOID *Context OPTIONAL, IN UINTN MemoryMapSize, IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN UINTN DescriptorSize)
BOOLEAN FindPattern(IN CONST UINT8 *Pattern, IN CONST UINT8 *PatternMask OPTIONAL, IN CONST UINT32 PatternSize, IN CONST UINT8 *Data, IN UINT32 DataSize, IN OUT UINT32 *DataOff)
Definition DataPatcher.c:82
UINT64 EFIAPI GetPseudoRandomNumber64(VOID)
Definition OcRngLib.c:408
#define L_STR_LEN(String)
Definition OcStringLib.h:26
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
Definition UserMath.c:25
UINT8 ValidSlides[TOTAL_SLIDE_NUM]