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; }