X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FDisk%2FPartitionDxe%2FGpt.c;h=aefb2d6ecb3f74b12957c511f8d0be6ee2e84c07;hp=6caec01a6cef0043eacee5a478799378de44b791;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=d0e9c3caebad80fbb8129f26ed6664f197501a9c
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
index 6caec01a6c..aefb2d6ecb 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
@@ -2,14 +2,20 @@
Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0
specification.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
-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
+ Caution: This file requires additional review when modified.
+ This driver will have external input - disk partition.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ PartitionInstallGptChildHandles() routine will read disk partition content and
+ do basic validation before PartitionInstallChildHandle().
+
+ PartitionValidGptTable(), PartitionCheckGptEntry() routine will accept disk
+ partition content and validate the GPT table and GPT entry.
+
+Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -19,6 +25,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
/**
Install child handles if the Handle supports GPT partition structure.
+ Caution: This function may receive untrusted input.
+ The GPT partition table header is external input, so this routine
+ will do basic validation for GPT partition table header before return.
+
@param[in] BlockIo Parent BlockIo interface.
@param[in] DiskIo Disk Io protocol.
@param[in] Lba The starting Lba of the Partition Table
@@ -77,12 +87,15 @@ PartitionRestoreGptTable (
/**
- Restore Partition Table to its alternate place.
- (Primary -> Backup or Backup -> Primary)
+ This routine will check GPT partition entry and return entry status.
+
+ Caution: This function may receive untrusted input.
+ The GPT partition entry is external input, so this routine
+ will do basic validation for GPT partition entry and report status.
@param[in] PartHeader Partition table header structure
@param[in] PartEntry The partition entry array
- @param[out] PEntryStatus the partition entry status array
+ @param[out] PEntryStatus the partition entry status array
recording the status of each partition
**/
@@ -158,9 +171,15 @@ PartitionSetCrc (
/**
Install child handles if the Handle supports GPT partition structure.
+ Caution: This function may receive untrusted input.
+ The GPT partition table is external input, so this routine
+ will do basic validation for GPT partition table before install
+ child handle for each GPT partition.
+
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path.
@@ -175,24 +194,26 @@ PartitionInstallGptChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
- EFI_STATUS Status;
- UINT32 BlockSize;
- EFI_LBA LastBlock;
- MASTER_BOOT_RECORD *ProtectiveMbr;
- EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
- EFI_PARTITION_TABLE_HEADER *BackupHeader;
- EFI_PARTITION_ENTRY *PartEntry;
- EFI_PARTITION_ENTRY *Entry;
- EFI_PARTITION_ENTRY_STATUS *PEntryStatus;
- UINTN Index;
- EFI_STATUS GptValidStatus;
- HARDDRIVE_DEVICE_PATH HdDev;
- UINT32 MediaId;
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ EFI_LBA LastBlock;
+ MASTER_BOOT_RECORD *ProtectiveMbr;
+ EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
+ EFI_PARTITION_TABLE_HEADER *BackupHeader;
+ EFI_PARTITION_ENTRY *PartEntry;
+ EFI_PARTITION_ENTRY *Entry;
+ EFI_PARTITION_ENTRY_STATUS *PEntryStatus;
+ UINTN Index;
+ EFI_STATUS GptValidStatus;
+ HARDDRIVE_DEVICE_PATH HdDev;
+ UINT32 MediaId;
+ EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
ProtectiveMbr = NULL;
PrimaryHeader = NULL;
@@ -209,6 +230,13 @@ PartitionInstallGptChildHandles (
GptValidStatus = EFI_NOT_FOUND;
+ //
+ // Ensure the block size can hold the MBR
+ //
+ if (BlockSize < sizeof (MASTER_BOOT_RECORD)) {
+ return EFI_NOT_FOUND;
+ }
+
//
// Allocate a buffer for the Protective MBR
//
@@ -284,7 +312,7 @@ PartitionInstallGptChildHandles (
DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));
DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));
if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {
- DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
+ DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
}
if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
@@ -355,17 +383,25 @@ PartitionInstallGptChildHandles (
}
ZeroMem (&HdDev, sizeof (HdDev));
- HdDev.Header.Type = MEDIA_DEVICE_PATH;
- HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
+ HdDev.Header.Type = MEDIA_DEVICE_PATH;
+ HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
- HdDev.PartitionNumber = (UINT32) Index + 1;
- HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
- HdDev.SignatureType = SIGNATURE_TYPE_GUID;
- HdDev.PartitionStart = Entry->StartingLBA;
- HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1;
+ HdDev.PartitionNumber = (UINT32) Index + 1;
+ HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
+ HdDev.SignatureType = SIGNATURE_TYPE_GUID;
+ HdDev.PartitionStart = Entry->StartingLBA;
+ HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1;
CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID));
+ ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
+ PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
+ PartitionInfo.Type = PARTITION_TYPE_GPT;
+ if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)) {
+ PartitionInfo.System = 1;
+ }
+ CopyMem (&PartitionInfo.Info.Gpt, Entry, sizeof (EFI_PARTITION_ENTRY));
+
DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index));
DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart));
DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA));
@@ -377,14 +413,16 @@ PartitionInstallGptChildHandles (
This,
Handle,
DiskIo,
+ DiskIo2,
BlockIo,
BlockIo2,
DevicePath,
(EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
+ &PartitionInfo,
Entry->StartingLBA,
Entry->EndingLBA,
BlockSize,
- CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)
+ &Entry->PartitionTypeGUID
);
}
@@ -411,7 +449,11 @@ Done:
}
/**
- Install child handles if the Handle supports GPT partition structure.
+ This routine will read GPT partition table header and return it.
+
+ Caution: This function may receive untrusted input.
+ The GPT partition table header is external input, so this routine
+ will do basic validation for GPT partition table header before return.
@param[in] BlockIo Parent BlockIo interface.
@param[in] DiskIo Disk Io protocol.
@@ -460,13 +502,22 @@ PartitionValidGptTable (
if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
!PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
- PartHdr->MyLBA != Lba
+ PartHdr->MyLBA != Lba ||
+ (PartHdr->SizeOfPartitionEntry < sizeof (EFI_PARTITION_ENTRY))
) {
DEBUG ((EFI_D_INFO, "Invalid efi partition table header\n"));
FreePool (PartHdr);
return FALSE;
}
+ //
+ // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.
+ //
+ if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {
+ FreePool (PartHdr);
+ return FALSE;
+ }
+
CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
FreePool (PartHdr);
@@ -640,12 +691,15 @@ Done:
}
/**
- Restore Partition Table to its alternate place.
- (Primary -> Backup or Backup -> Primary)
+ This routine will check GPT partition entry and return entry status.
+
+ Caution: This function may receive untrusted input.
+ The GPT partition entry is external input, so this routine
+ will do basic validation for GPT partition entry and report status.
@param[in] PartHeader Partition table header structure
@param[in] PartEntry The partition entry array
- @param[out] PEntryStatus the partition entry status array
+ @param[out] PEntryStatus the partition entry status array
recording the status of each partition
**/
@@ -683,7 +737,7 @@ PartitionCheckGptEntry (
if ((Entry->Attributes & BIT1) != 0) {
//
- // If Bit 1 is set, this indicate that this is an OS specific GUID partition.
+ // If Bit 1 is set, this indicate that this is an OS specific GUID partition.
//
PEntryStatus[Index1].OsSpecific = TRUE;
}