84b8cf78847c06143b70d6d07e42d983ac2c7da5
[mirror_edk2.git] / SecurityPkg / Library / DxeDeferImageLoadLib / DxeDeferImageLoadLib.c
1 /** @file
2 Implement defer image load services for user identification in UEFI2.2.
3
4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "DxeDeferImageLoadLib.h"
16
17 //
18 // Handle for the Deferred Image Load Protocol instance produced by this driver.
19 //
20 EFI_HANDLE mDeferredImageHandle = NULL;
21 BOOLEAN mIsProtocolInstalled = FALSE;
22 EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
23 DEFERRED_IMAGE_TABLE mDeferredImage = {
24 0, // Deferred image count
25 NULL // The deferred image info
26 };
27
28 EFI_DEFERRED_IMAGE_LOAD_PROTOCOL gDeferredImageLoad = {
29 GetDefferedImageInfo
30 };
31
32 /**
33 Get the image type.
34
35 @param[in] File This is a pointer to the device path of the file
36 that is being dispatched.
37
38 @return UINT32 Image Type
39
40 **/
41 UINT32
42 GetFileType (
43 IN CONST EFI_DEVICE_PATH_PROTOCOL *File
44 )
45 {
46 EFI_STATUS Status;
47 EFI_HANDLE DeviceHandle;
48 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
49 EFI_BLOCK_IO_PROTOCOL *BlockIo;
50
51 //
52 // First check to see if File is from a Firmware Volume
53 //
54 DeviceHandle = NULL;
55 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
56 Status = gBS->LocateDevicePath (
57 &gEfiFirmwareVolume2ProtocolGuid,
58 &TempDevicePath,
59 &DeviceHandle
60 );
61 if (!EFI_ERROR (Status)) {
62 Status = gBS->OpenProtocol (
63 DeviceHandle,
64 &gEfiFirmwareVolume2ProtocolGuid,
65 NULL,
66 NULL,
67 NULL,
68 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
69 );
70 if (!EFI_ERROR (Status)) {
71 return IMAGE_FROM_FV;
72 }
73 }
74
75 //
76 // Next check to see if File is from a Block I/O device
77 //
78 DeviceHandle = NULL;
79 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
80 Status = gBS->LocateDevicePath (
81 &gEfiBlockIoProtocolGuid,
82 &TempDevicePath,
83 &DeviceHandle
84 );
85 if (!EFI_ERROR (Status)) {
86 BlockIo = NULL;
87 Status = gBS->OpenProtocol (
88 DeviceHandle,
89 &gEfiBlockIoProtocolGuid,
90 (VOID **) &BlockIo,
91 NULL,
92 NULL,
93 EFI_OPEN_PROTOCOL_GET_PROTOCOL
94 );
95 if (!EFI_ERROR (Status) && BlockIo != NULL) {
96 if (BlockIo->Media != NULL) {
97 if (BlockIo->Media->RemovableMedia) {
98 //
99 // Block I/O is present and specifies the media is removable
100 //
101 return IMAGE_FROM_REMOVABLE_MEDIA;
102 } else {
103 //
104 // Block I/O is present and specifies the media is not removable
105 //
106 return IMAGE_FROM_FIXED_MEDIA;
107 }
108 }
109 }
110 }
111
112 //
113 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
114 // the device path supports the Simple File System Protocol.
115 //
116 DeviceHandle = NULL;
117 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
118 Status = gBS->LocateDevicePath (
119 &gEfiSimpleFileSystemProtocolGuid,
120 &TempDevicePath,
121 &DeviceHandle
122 );
123 if (!EFI_ERROR (Status)) {
124 //
125 // Simple File System is present without Block I/O, so assume media is fixed.
126 //
127 return IMAGE_FROM_FIXED_MEDIA;
128 }
129
130 //
131 // File is not from an FV, Block I/O or Simple File System, so the only options
132 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
133 //
134 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
135 while (!IsDevicePathEndType (TempDevicePath)) {
136 switch (DevicePathType (TempDevicePath)) {
137
138 case MEDIA_DEVICE_PATH:
139 if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
140 return IMAGE_FROM_OPTION_ROM;
141 }
142 break;
143
144 case MESSAGING_DEVICE_PATH:
145 if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
146 return IMAGE_FROM_REMOVABLE_MEDIA;
147 }
148 break;
149
150 default:
151 break;
152 }
153 TempDevicePath = NextDevicePathNode (TempDevicePath);
154 }
155 return IMAGE_UNKNOWN;
156 }
157
158
159 /**
160 Get current user's access right.
161
162 @param[out] AccessControl Points to the user's access control data, the
163 caller should free data buffer.
164 @param[in] AccessType The type of user access control.
165
166 @retval EFI_SUCCESS Get current user access control successfully
167 @retval others Fail to get current user access control
168
169 **/
170 EFI_STATUS
171 GetAccessControl (
172 OUT EFI_USER_INFO_ACCESS_CONTROL **AccessControl,
173 IN UINT32 AccessType
174 )
175 {
176 EFI_STATUS Status;
177 EFI_USER_INFO_HANDLE UserInfo;
178 EFI_USER_INFO *Info;
179 UINTN InfoSize;
180 EFI_USER_INFO_ACCESS_CONTROL *Access;
181 EFI_USER_PROFILE_HANDLE CurrentUser;
182 UINTN CheckLen;
183 EFI_USER_MANAGER_PROTOCOL *UserManager;
184
185 CurrentUser = NULL;
186 Status = gBS->LocateProtocol (
187 &gEfiUserManagerProtocolGuid,
188 NULL,
189 (VOID **) &UserManager
190 );
191 if (EFI_ERROR (Status)) {
192 return EFI_NOT_FOUND;
193 }
194
195 //
196 // Get current user access information.
197 //
198 UserManager->Current (UserManager, &CurrentUser);
199
200 UserInfo = NULL;
201 Info = NULL;
202 InfoSize = 0;
203 while (TRUE) {
204 //
205 // Get next user information.
206 //
207 Status = UserManager->GetNextInfo (UserManager, CurrentUser, &UserInfo);
208 if (EFI_ERROR (Status)) {
209 return Status;
210 }
211
212 Status = UserManager->GetInfo (
213 UserManager,
214 CurrentUser,
215 UserInfo,
216 Info,
217 &InfoSize
218 );
219 if (Status == EFI_BUFFER_TOO_SMALL) {
220 if (Info != NULL) {
221 FreePool (Info);
222 }
223 Info = AllocateZeroPool (InfoSize);
224 ASSERT (Info != NULL);
225 Status = UserManager->GetInfo (
226 UserManager,
227 CurrentUser,
228 UserInfo,
229 Info,
230 &InfoSize
231 );
232 }
233
234 if (EFI_ERROR (Status)) {
235 break;
236 }
237
238 ASSERT (Info != NULL);
239 if (Info->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) {
240 continue;
241 }
242
243 //
244 // Get specified access information.
245 //
246 CheckLen = 0;
247 while (CheckLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {
248 Access = (EFI_USER_INFO_ACCESS_CONTROL *) ((UINT8 *) (Info + 1) + CheckLen);
249 if ((Access->Type == AccessType)) {
250 *AccessControl = AllocateZeroPool (Access->Size);
251 ASSERT (*AccessControl != NULL);
252 CopyMem (*AccessControl, Access, Access->Size);
253 FreePool (Info);
254 return EFI_SUCCESS;
255 }
256 CheckLen += Access->Size;
257 }
258 }
259
260 if (Info != NULL) {
261 FreePool (Info);
262 }
263 return EFI_NOT_FOUND;
264 }
265
266
267 /**
268 Convert the '/' to '\' in the specified string.
269
270 @param[in, out] Str Points to the string to convert.
271
272 **/
273 VOID
274 ConvertDPStr (
275 IN OUT EFI_STRING Str
276 )
277 {
278 INTN Count;
279 INTN Index;
280
281 Count = StrSize(Str) / 2 - 1;
282
283 if (Count < 4) {
284 return;
285 }
286
287 //
288 // Convert device path string.
289 //
290 Index = Count - 1;
291 while (Index > 0) {
292 //
293 // Find the last '/'.
294 //
295 for (Index = Count - 1; Index > 0; Index--) {
296 if (Str[Index] == L'/')
297 break;
298 }
299
300 //
301 // Check next char.
302 //
303 if (Str[Index + 1] == L'\\')
304 return;
305
306 Str[Index] = L'\\';
307
308 //
309 // Check previous char.
310 //
311 if ((Index > 0) && (Str[Index - 1] == L'\\')) {
312 CopyMem (&Str[Index - 1], &Str[Index], (UINTN) ((Count - Index + 1) * sizeof (CHAR16)));
313 return;
314 }
315 Index--;
316 }
317 }
318
319
320 /**
321 Check whether the DevicePath2 is identical with DevicePath1, or identical with
322 DevicePath1's child device path.
323
324 If DevicePath2 is identical with DevicePath1, or with DevicePath1's child device
325 path, then TRUE returned. Otherwise, FALSE is returned.
326
327 If DevicePath1 is NULL, then ASSERT().
328 If DevicePath2 is NULL, then ASSERT().
329
330 @param[in] DevicePath1 A pointer to a device path.
331 @param[in] DevicePath2 A pointer to a device path.
332
333 @retval TRUE Two device paths are identical , or DevicePath2 is
334 DevicePath1's child device path.
335 @retval FALSE Two device paths are not identical, and DevicePath2
336 is not DevicePath1's child device path.
337
338 **/
339 BOOLEAN
340 CheckDevicePath (
341 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
342 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2
343 )
344 {
345 EFI_STATUS Status;
346 EFI_STRING DevicePathStr1;
347 EFI_STRING DevicePathStr2;
348 UINTN StrLen1;
349 UINTN StrLen2;
350 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText;
351 BOOLEAN DevicePathEqual;
352
353 ASSERT (DevicePath1 != NULL);
354 ASSERT (DevicePath2 != NULL);
355
356 DevicePathEqual = FALSE;
357 DevicePathText = NULL;
358 Status = gBS->LocateProtocol (
359 &gEfiDevicePathToTextProtocolGuid,
360 NULL,
361 (VOID **) &DevicePathText
362 );
363 ASSERT (Status == EFI_SUCCESS);
364
365 //
366 // Get first device path string.
367 //
368 DevicePathStr1 = DevicePathText->ConvertDevicePathToText (DevicePath1, TRUE, TRUE);
369 ConvertDPStr (DevicePathStr1);
370 //
371 // Get second device path string.
372 //
373 DevicePathStr2 = DevicePathText->ConvertDevicePathToText (DevicePath2, TRUE, TRUE);
374 ConvertDPStr (DevicePathStr2);
375
376 //
377 // Compare device path string.
378 //
379 StrLen1 = StrSize (DevicePathStr1);
380 StrLen2 = StrSize (DevicePathStr2);
381 if (StrLen1 > StrLen2) {
382 DevicePathEqual = FALSE;
383 goto Done;
384 }
385
386 if (CompareMem (DevicePathStr1, DevicePathStr2, StrLen1) == 0) {
387 DevicePathEqual = TRUE;
388 }
389
390 Done:
391 FreePool (DevicePathStr1);
392 FreePool (DevicePathStr2);
393 return DevicePathEqual;
394 }
395
396
397 /**
398 Check whether the image pointed to by DevicePath is in the device path list
399 specified by AccessType.
400
401 @param[in] DevicePath Points to device path.
402 @param[in] AccessType The type of user access control.
403
404 @retval TURE The DevicePath is in the specified List.
405 @retval FALSE The DevicePath is not in the specified List.
406
407 **/
408 BOOLEAN
409 IsDevicePathInList (
410 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
411 IN UINT32 AccessType
412 )
413 {
414 EFI_STATUS Status;
415 EFI_USER_INFO_ACCESS_CONTROL *Access;
416 EFI_DEVICE_PATH_PROTOCOL *Path;
417 UINTN OffSet;
418
419 Status = GetAccessControl (&Access, AccessType);
420 if (EFI_ERROR (Status)) {
421 return FALSE;
422 }
423
424 OffSet = 0;
425 while (OffSet < Access->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
426 Path = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)(Access + 1) + OffSet);
427 if (CheckDevicePath (Path, DevicePath)) {
428 //
429 // The device path is found in list.
430 //
431 FreePool (Access);
432 return TRUE;
433 }
434 OffSet += GetDevicePathSize (Path);
435 }
436
437 FreePool (Access);
438 return FALSE;
439 }
440
441
442 /**
443 Check whether the image pointed to by DevicePath is permitted to load.
444
445 @param[in] DevicePath Points to device path
446
447 @retval TURE The image pointed by DevicePath is permitted to load.
448 @retval FALSE The image pointed by DevicePath is forbidden to load.
449
450 **/
451 BOOLEAN
452 VerifyDevicePath (
453 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
454 )
455 {
456 if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_PERMIT_LOAD)) {
457 //
458 // This access control overrides any restrictions put in place by the
459 // EFI_USER_INFO_ACCESS_FORBID_LOAD record.
460 //
461 return TRUE;
462 }
463
464 if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_FORBID_LOAD)) {
465 //
466 // The device path is found in the forbidden list.
467 //
468 return FALSE;
469 }
470
471 return TRUE;
472 }
473
474
475 /**
476 Check the image pointed by DevicePath is a boot option or not.
477
478 @param[in] DevicePath Points to device path.
479
480 @retval TURE The image pointed by DevicePath is a boot option.
481 @retval FALSE The image pointed by DevicePath is not a boot option.
482
483 **/
484 BOOLEAN
485 IsBootOption (
486 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
487 )
488 {
489 EFI_STATUS Status;
490 UINT16 *BootOrderList;
491 UINTN BootOrderListSize;
492 UINTN Index;
493 CHAR16 StrTemp[20];
494 UINT8 *OptionBuffer;
495 UINT8 *OptionPtr;
496 EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
497
498 //
499 // Get BootOrder
500 //
501 BootOrderListSize = 0;
502 BootOrderList = NULL;
503 Status = gRT->GetVariable (
504 L"BootOrder",
505 &gEfiGlobalVariableGuid,
506 NULL,
507 &BootOrderListSize,
508 NULL
509 );
510 if (Status == EFI_BUFFER_TOO_SMALL) {
511 BootOrderList = AllocateZeroPool (BootOrderListSize);
512 ASSERT (BootOrderList != NULL);
513 Status = gRT->GetVariable (
514 L"BootOrder",
515 &gEfiGlobalVariableGuid,
516 NULL,
517 &BootOrderListSize,
518 BootOrderList
519 );
520 }
521
522 if (EFI_ERROR (Status)) {
523 //
524 // No Boot option
525 //
526 return FALSE;
527 }
528
529 OptionBuffer = NULL;
530 for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
531 //
532 // Try to find the DevicePath in BootOption
533 //
534 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);
535 GetEfiGlobalVariable2 (StrTemp, (VOID**)&OptionBuffer, NULL);
536 if (OptionBuffer == NULL) {
537 continue;
538 }
539
540 //
541 // Check whether the image is forbidden.
542 //
543
544 OptionPtr = OptionBuffer;
545 //
546 // Skip attribute.
547 //
548 OptionPtr += sizeof (UINT32);
549
550 //
551 // Skip device path length.
552 //
553 OptionPtr += sizeof (UINT16);
554
555 //
556 // Skip descript string
557 //
558 OptionPtr += StrSize ((UINT16 *) OptionPtr);
559
560 //
561 // Now OptionPtr points to Device Path.
562 //
563 OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) OptionPtr;
564
565 if (CheckDevicePath (DevicePath, OptionDevicePath)) {
566 FreePool (OptionBuffer);
567 OptionBuffer = NULL;
568 return TRUE;
569 }
570 FreePool (OptionBuffer);
571 OptionBuffer = NULL;
572 }
573
574 if (BootOrderList != NULL) {
575 FreePool (BootOrderList);
576 }
577
578 return FALSE;
579 }
580
581
582 /**
583 Add the image info to a deferred image list.
584
585 @param[in] ImageDevicePath A pointer to the device path of a image.
586 @param[in] Image Points to the first byte of the image, or NULL if the
587 image is not available.
588 @param[in] ImageSize The size of the image, or 0 if the image is not available.
589
590 **/
591 VOID
592 PutDefferedImageInfo (
593 IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
594 IN VOID *Image,
595 IN UINTN ImageSize
596 )
597 {
598 DEFERRED_IMAGE_INFO *CurImageInfo;
599 UINTN PathSize;
600
601 //
602 // Expand memory for the new deferred image.
603 //
604 if (mDeferredImage.Count == 0) {
605 mDeferredImage.ImageInfo = AllocatePool (sizeof (DEFERRED_IMAGE_INFO));
606 ASSERT (mDeferredImage.ImageInfo != NULL);
607 } else {
608 CurImageInfo = AllocatePool ((mDeferredImage.Count + 1) * sizeof (DEFERRED_IMAGE_INFO));
609 ASSERT (CurImageInfo != NULL);
610
611 CopyMem (
612 CurImageInfo,
613 mDeferredImage.ImageInfo,
614 mDeferredImage.Count * sizeof (DEFERRED_IMAGE_INFO)
615 );
616 FreePool (mDeferredImage.ImageInfo);
617 mDeferredImage.ImageInfo = CurImageInfo;
618 }
619 mDeferredImage.Count++;
620
621 //
622 // Save the deferred image information.
623 //
624 CurImageInfo = &mDeferredImage.ImageInfo[mDeferredImage.Count - 1];
625 PathSize = GetDevicePathSize (ImageDevicePath);
626 CurImageInfo->ImageDevicePath = AllocateZeroPool (PathSize);
627 ASSERT (CurImageInfo->ImageDevicePath != NULL);
628 CopyMem (CurImageInfo->ImageDevicePath, ImageDevicePath, PathSize);
629
630 CurImageInfo->Image = Image;
631 CurImageInfo->ImageSize = ImageSize;
632 CurImageInfo->BootOption = IsBootOption (ImageDevicePath);
633 }
634
635
636 /**
637 Returns information about a deferred image.
638
639 This function returns information about a single deferred image. The deferred images are
640 numbered consecutively, starting with 0. If there is no image which corresponds to
641 ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by
642 iteratively calling this function until EFI_NOT_FOUND is returned.
643 Image may be NULL and ImageSize set to 0 if the decision to defer execution was made
644 because of the location of the executable image, rather than its actual contents.
645
646 @param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.
647 @param[in] ImageIndex Zero-based index of the deferred index.
648 @param[out] ImageDevicePath On return, points to a pointer to the device path of the image.
649 The device path should not be freed by the caller.
650 @param[out] Image On return, points to the first byte of the image or NULL if the
651 image is not available. The image should not be freed by the caller
652 unless LoadImage() has been successfully called.
653 @param[out] ImageSize On return, the size of the image, or 0 if the image is not available.
654 @param[out] BootOption On return, points to TRUE if the image was intended as a boot option
655 or FALSE if it was not intended as a boot option.
656
657 @retval EFI_SUCCESS Image information returned successfully.
658 @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image.
659 @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or
660 BootOption is NULL.
661
662 **/
663 EFI_STATUS
664 EFIAPI
665 GetDefferedImageInfo (
666 IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This,
667 IN UINTN ImageIndex,
668 OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath,
669 OUT VOID **Image,
670 OUT UINTN *ImageSize,
671 OUT BOOLEAN *BootOption
672 )
673 {
674 DEFERRED_IMAGE_INFO *ReqImageInfo;
675
676 //
677 // Check the parameter.
678 //
679
680 if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) {
681 return EFI_INVALID_PARAMETER;
682 }
683
684 if ((ImageDevicePath == NULL) || (BootOption == NULL)) {
685 return EFI_INVALID_PARAMETER;
686 }
687
688 if (ImageIndex >= mDeferredImage.Count) {
689 return EFI_NOT_FOUND;
690 }
691
692 //
693 // Get the request deferred image.
694 //
695 ReqImageInfo = &mDeferredImage.ImageInfo[ImageIndex];
696
697 *ImageDevicePath = ReqImageInfo->ImageDevicePath;
698 *Image = ReqImageInfo->Image;
699 *ImageSize = ReqImageInfo->ImageSize;
700 *BootOption = ReqImageInfo->BootOption;
701
702 return EFI_SUCCESS;
703 }
704
705
706 /**
707 Provides the service of deferring image load based on platform policy control,
708 and installs Deferred Image Load Protocol.
709
710 @param[in] AuthenticationStatus This is the authentication status returned from the
711 security measurement services for the input file.
712 @param[in] File This is a pointer to the device path of the file that
713 is being dispatched. This will optionally be used for
714 logging.
715 @param[in] FileBuffer File buffer matches the input file device path.
716 @param[in] FileSize Size of File buffer matches the input file device path.
717
718 @retval EFI_SUCCESS The file specified by File did authenticate, and the
719 platform policy dictates that the DXE Core may use File.
720 @retval EFI_INVALID_PARAMETER File is NULL.
721 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
722 the platform policy dictates that File should be placed
723 in the untrusted state. A file may be promoted from
724 the untrusted to the trusted state at a future time
725 with a call to the Trust() DXE Service.
726 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
727 the platform policy dictates that File should not be
728 used for any purpose.
729
730 **/
731 EFI_STATUS
732 EFIAPI
733 DxeDeferImageLoadHandler (
734 IN UINT32 AuthenticationStatus,
735 IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
736 IN VOID *FileBuffer,
737 IN UINTN FileSize
738 )
739
740 {
741 EFI_STATUS Status;
742 EFI_USER_PROFILE_HANDLE CurrentUser;
743 UINT32 Policy;
744 UINT32 FileType;
745
746 if (File == NULL) {
747 return EFI_INVALID_PARAMETER;
748 }
749
750 //
751 // Check whether user has a logon.
752 //
753 CurrentUser = NULL;
754 if (mUserManager != NULL) {
755 mUserManager->Current (mUserManager, &CurrentUser);
756 if (CurrentUser != NULL) {
757 //
758 // The user is logon; verify the FilePath by current user access policy.
759 //
760 if (!VerifyDevicePath (File)) {
761 DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n"));
762 return EFI_ACCESS_DENIED;
763 }
764 return EFI_SUCCESS;
765 }
766 }
767
768 //
769 // Still no user logon.
770 // Check the file type and get policy setting.
771 //
772 FileType = GetFileType (File);
773 Policy = PcdGet32 (PcdDeferImageLoadPolicy);
774 if ((Policy & FileType) == FileType) {
775 //
776 // This file type is secure to load.
777 //
778 return EFI_SUCCESS;
779 }
780
781 DEBUG ((EFI_D_ERROR, "[Security] No user identified, the image is deferred to load!\n"));
782 PutDefferedImageInfo (File, NULL, 0);
783
784 //
785 // Install the Deferred Image Load Protocol onto a new handle.
786 //
787 if (!mIsProtocolInstalled) {
788 Status = gBS->InstallMultipleProtocolInterfaces (
789 &mDeferredImageHandle,
790 &gEfiDeferredImageLoadProtocolGuid,
791 &gDeferredImageLoad,
792 NULL
793 );
794 ASSERT_EFI_ERROR (Status);
795 mIsProtocolInstalled = TRUE;
796 }
797
798 return EFI_ACCESS_DENIED;
799 }
800
801 /**
802 Locate user manager protocol when user manager is installed.
803
804 @param[in] Event The Event that is being processed, not used.
805 @param[in] Context Event Context, not used.
806
807 **/
808 VOID
809 EFIAPI
810 FindUserManagerProtocol (
811 IN EFI_EVENT Event,
812 IN VOID* Context
813 )
814 {
815 gBS->LocateProtocol (
816 &gEfiUserManagerProtocolGuid,
817 NULL,
818 (VOID **) &mUserManager
819 );
820
821 }
822
823
824 /**
825 Register security handler for deferred image load.
826
827 @param[in] ImageHandle ImageHandle of the loaded driver.
828 @param[in] SystemTable Pointer to the EFI System Table.
829
830 @retval EFI_SUCCESS The handlers were registered successfully.
831 **/
832 EFI_STATUS
833 EFIAPI
834 DxeDeferImageLoadLibConstructor (
835 IN EFI_HANDLE ImageHandle,
836 IN EFI_SYSTEM_TABLE *SystemTable
837 )
838 {
839 VOID *Registration;
840
841 //
842 // Register user manager notification function.
843 //
844 EfiCreateProtocolNotifyEvent (
845 &gEfiUserManagerProtocolGuid,
846 TPL_CALLBACK,
847 FindUserManagerProtocol,
848 NULL,
849 &Registration
850 );
851
852 return RegisterSecurityHandler (
853 DxeDeferImageLoadHandler,
854 EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD
855 );
856 }
857
858