OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
PeCoff.c
Go to the documentation of this file.
1
6#include "../Include/Uefi.h"
7
8#include <Library/BaseMemoryLib.h>
9#include <Library/BaseOverflowLib.h>
10#include <Library/MemoryAllocationLib.h>
11#include <Library/PeCoffLib2.h>
12#include <Library/DebugLib.h>
13#include <Library/UefiBootServicesTableLib.h>
14
15#include <stdio.h>
16#include <string.h>
17
18#include <UserFile.h>
19#include <UserMemory.h>
20
21STATIC UINT64 mHashesMask = MAX_UINT64;
22STATIC UINTN mHashIndex = 0;
23STATIC UINTN mHashDependency;
24
25STATIC
26BOOLEAN
28 IN OUT VOID *HashContext,
29 IN CONST VOID *Data,
30 IN UINTN DataLength
31 )
32{
33 CONST UINT8 *D;
34
35 D = (CONST UINT8 *)Data;
36
37 (VOID)HashContext;
38
39 BOOLEAN P;
40
41 for (UINTN i = 0; i < DataLength; i++) {
42 mHashDependency += D[i];
43 }
44
45 if ((mHashesMask & (1ULL << mHashIndex)) != 0) {
46 P = TRUE;
47 } else {
48 P = FALSE;
49 }
50
51 ++mHashIndex;
52 mHashIndex &= 63U;
53
54 return P;
55}
56
57STATIC
58EFI_STATUS
60 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
61 )
62{
63 EFI_STATUS Status;
64 PE_COFF_LOADER_RUNTIME_CONTEXT *RtCtx;
65 UINT32 RtCtxSize;
66
67 Status = PeCoffLoaderGetRuntimeContextSize (Context, &RtCtxSize);
68 if (EFI_ERROR (Status)) {
69 return EFI_UNSUPPORTED;
70 }
71
72 RtCtx = AllocatePool (RtCtxSize);
73 if (RtCtx == NULL) {
74 return EFI_UNSUPPORTED;
75 }
76
77 Status = PeCoffRelocateImage (Context, 0x69696969, RtCtx, RtCtxSize);
78 if (EFI_ERROR (Status)) {
79 FreePool (RtCtx);
80 return Status;
81 }
82
83 Status = PeCoffRuntimeRelocateImage (Context->ImageBuffer, Context->SizeOfImage, 0x96969696, RtCtx);
84
85 FreePool (RtCtx);
86
87 return Status;
88}
89
90STATIC
91EFI_STATUS
93 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
94 OUT VOID *Destination,
95 IN UINT32 DestinationSize
96 )
97{
98 EFI_STATUS Status;
99 CHAR8 *PdbPath;
100 UINT32 PdbPathSize;
101
102 Status = PeCoffLoadImage (Context, Destination, DestinationSize);
103 if (EFI_ERROR (Status)) {
104 return Status;
105 }
106
107 Status = PeCoffGetPdbPath (Context, (CONST CHAR8 **)&PdbPath, &PdbPathSize);
108 if (!EFI_ERROR (Status)) {
109 ZeroMem (PdbPath, PdbPathSize);
110 }
111
112 if (!Context->RelocsStripped) {
113 if (Context->Subsystem != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
114 Status = PeCoffRelocateImage (Context, (UINTN)(Context->ImageBuffer), NULL, 0);
115 } else {
116 Status = PeCoffTestRtReloc (Context);
117 }
118 }
119
120 if (EFI_ERROR (Status)) {
121 return Status;
122 }
123
124 PeCoffDiscardSections (Context);
125
126 return EFI_SUCCESS;
127}
128
129STATIC
130VOID
132 IN CONST UINT8 *Data,
133 IN UINTN Size
134 )
135{
136 UINT32 ConfigSize;
137 UINT32 LastByte;
138
139 mHashDependency = 0;
140 mHashIndex = 0;
141
142 ConfigSize = 0;
143
144 if (Size - ConfigSize >= sizeof (UINT8)) {
145 ConfigSize += sizeof (UINT8);
146 LastByte = Data[Size - ConfigSize];
147 } else {
148 LastByte = MAX_UINT8;
149 }
150
151 PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch) = (LastByte & 1U) != 0;
152 PcdGetBool (PcdImageLoaderHashProhibitOverlap) = (LastByte & 2U) != 0;
153 PcdGetBool (PcdImageLoaderLoadHeader) = (LastByte & 4U) != 0;
154 PcdGetBool (PcdImageLoaderDebugSupport) = (LastByte & 8U) != 0;
155 PcdGetBool (PcdImageLoaderAllowMisalignedOffset) = (LastByte & 16U) != 0;
156 PcdGetBool (PcdImageLoaderRemoveXForWX) = (LastByte & 32U) != 0;
157
158 if (Size - ConfigSize >= sizeof (UINT32)) {
159 ConfigSize += sizeof (UINT32);
160 CopyMem (&LastByte, &Data[Size - ConfigSize], sizeof (UINT32));
161 } else {
162 LastByte = MAX_UINT32;
163 }
164
165 PcdGet32 (PcdImageLoaderAlignmentPolicy) = LastByte;
166
167 if (Size - ConfigSize >= sizeof (UINT32)) {
168 ConfigSize += sizeof (UINT32);
169 CopyMem (&LastByte, &Data[Size - ConfigSize], sizeof (UINT32));
170 } else {
171 LastByte = MAX_UINT32;
172 }
173
174 PcdGet32 (PcdImageLoaderRelocTypePolicy) = LastByte;
175
176 ConfigureMemoryAllocations (Data, Size, &ConfigSize);
177
178 if (Size - ConfigSize >= sizeof (UINT64)) {
179 ConfigSize += sizeof (UINT64);
180 CopyMem (&mHashesMask, &Data[Size - ConfigSize], sizeof (UINT64));
181 } else {
182 mHashesMask = MAX_UINT64;
183 }
184}
185
186STATIC
187EFI_STATUS
189 IN CONST VOID *FileBuffer,
190 IN UINT32 FileSize
191 )
192{
193 EFI_STATUS Status;
194 BOOLEAN Result;
195 PE_COFF_LOADER_IMAGE_CONTEXT Context;
196 VOID *Destination;
197 UINT32 ImageSize;
198 UINT32 DestinationSize;
199 UINT32 DestinationPages;
200 UINT32 DestinationAlignment;
201 UINT8 HashContext;
202
203 Status = PeCoffInitializeContext (&Context, FileBuffer, FileSize, UefiImageOriginFv);
204 if (EFI_ERROR (Status)) {
205 return EFI_UNSUPPORTED;
206 }
207
208 Result = PeCoffHashImageAuthenticode (
209 &Context,
210 &HashContext,
212 );
213 if (!Result) {
214 return EFI_UNSUPPORTED;
215 }
216
217 ImageSize = PeCoffGetSizeOfImage (&Context);
218 DestinationPages = EFI_SIZE_TO_PAGES (ImageSize);
219 DestinationSize = EFI_PAGES_TO_SIZE (DestinationPages);
220 DestinationAlignment = PeCoffGetSectionAlignment (&Context);
221
222 if (DestinationSize >= BASE_16MB) {
223 return EFI_UNSUPPORTED;
224 }
225
226 Destination = AllocateAlignedCodePages (
227 DestinationPages,
228 DestinationAlignment
229 );
230 if (Destination == NULL) {
231 return EFI_UNSUPPORTED;
232 }
233
234 Status = PeCoffTestLoad (&Context, Destination, DestinationSize);
235
236 FreeAlignedPages (Destination, DestinationPages);
237
238 return Status;
239}
240
241int
243 const uint8_t *Data,
244 size_t Size
245 )
246{
247 VOID *NewData;
248
249 if (Size == 0) {
250 return 0;
251 }
252
253 PcdGet8 (PcdDebugRaisePropertyMask) = 0;
254 // PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
255 // PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
256
257 LoadConfig (Data, Size);
258
259 NewData = AllocatePool (Size);
260 if (NewData != NULL) {
261 CopyMem (NewData, Data, Size);
262 PeCoffTestLoadFull (NewData, Size);
263 FreePool (NewData);
264 }
265
266 DEBUG ((
267 DEBUG_POOL | DEBUG_PAGE,
268 "UMEM: Allocated %u pools %u pages\n",
269 (UINT32)mPoolAllocations,
270 (UINT32)mPageAllocations
271 ));
272
273 return 0;
274}
275
276int
278 int argc,
279 char *argv[]
280 )
281{
282 UINT8 *Image;
283 UINT32 ImageSize;
284 EFI_STATUS Status;
285
286 if (argc < 2) {
287 DEBUG ((DEBUG_ERROR, "Please provide a valid PE image path\n"));
288 return -1;
289 }
290
291 PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_INFO;
292 PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_INFO;
293
294 //
295 // Images may be not 4KBi aligned.
296 //
297 PcdGet32 (PcdImageProtectionPolicy) = 0x00;
298
299 // PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
300 // PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
301
302 if ((Image = UserReadFile (argv[1], &ImageSize)) == NULL) {
303 DEBUG ((DEBUG_ERROR, "Read fail\n"));
304 return 1;
305 }
306
307 Status = LLVMFuzzerTestOneInput (Image, ImageSize);
308 FreePool (Image);
309 if (EFI_ERROR (Status)) {
310 return 1;
311 }
312
313 return 0;
314}
DMG_SIZE_DEVICE_PATH Size
STATIC UINTN mHashDependency
Definition PeCoff.c:23
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Definition PeCoff.c:242
STATIC VOID LoadConfig(IN CONST UINT8 *Data, IN UINTN Size)
Definition PeCoff.c:131
STATIC UINT64 mHashesMask
Definition PeCoff.c:21
STATIC BOOLEAN HashUpdate(IN OUT VOID *HashContext, IN CONST VOID *Data, IN UINTN DataLength)
Definition PeCoff.c:27
STATIC EFI_STATUS PeCoffTestLoad(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context, OUT VOID *Destination, IN UINT32 DestinationSize)
Definition PeCoff.c:92
STATIC EFI_STATUS PeCoffTestRtReloc(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context)
Definition PeCoff.c:59
STATIC EFI_STATUS PeCoffTestLoadFull(IN CONST VOID *FileBuffer, IN UINT32 FileSize)
Definition PeCoff.c:188
STATIC UINTN mHashIndex
Definition PeCoff.c:22
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT8 * UserReadFile(IN CONST CHAR8 *FileName, OUT UINT32 *Size)
Definition UserFile.c:62
UINTN mPageAllocations
UINTN mPoolAllocations
VOID ConfigureMemoryAllocations(IN CONST UINT8 *Data, IN UINTN Size, IN OUT UINT32 *ConfigSize)
UINT8 uint8_t
int ENTRY_POINT(void)