From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 31A7B20958965 for ; Wed, 5 Jul 2017 09:40:48 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A567D7C83B; Wed, 5 Jul 2017 16:42:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A567D7C83B Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=lersek@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com A567D7C83B Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-25.phx2.redhat.com [10.3.116.25]) by smtp.corp.redhat.com (Postfix) with ESMTP id 17B6C7E907; Wed, 5 Jul 2017 16:42:20 +0000 (UTC) From: Laszlo Ersek To: edk2-devel-01 Cc: Ard Biesheuvel , Gerd Hoffmann , Leif Lindholm , Liming Gao , Yonghong Zhu Date: Wed, 5 Jul 2017 18:42:18 +0200 Message-Id: <20170705164218.25814-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 05 Jul 2017 16:42:27 +0000 (UTC) Subject: [PATCH] BaseTools/GenFw: work around GNU Binutils bug wrt. DebugDirectoryEntrySize X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Jul 2017 16:40:48 -0000 GNU Binutils produce a PE debug directory with one EFI_IMAGE_DEBUG_DIRECTORY_ENTRY: - the Type field of the entry is EFI_IMAGE_DEBUG_TYPE_CODEVIEW, - the FileOffset field of the entry points right past the entry itself, - the data structure placed at FileOffset is a CV_INFO_PDB20 structure, with an "NB10" signature. This is all correct, except GNU Binutils include the pointed-to CV_INFO_PDB20 structure in the size of the debug directory (that is, Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size). That's a bug. The malformed debug directory size causes the loop in GenFw's ZeroDebugData() function to process the CV_INFO_PDB20 structure as a set of EFI_IMAGE_DEBUG_DIRECTORY_ENTRY elements, which crashes GenFw. This problem was exposed by commit e4129b0e5897 ("BaseTools: Update GenFw to clear unused debug entry generated by VS tool chain", 2017-06-19). Work around the Binutils issue by noticing when an EFI_IMAGE_DEBUG_DIRECTORY_ENTRY.FileOffset points back into the debug directory. (This can never happen with a well-formed PE file.) In this case, truncate DebugDirectoryEntrySize such that the debug directory will end right before the debug structure pointed-to by EFI_IMAGE_DEBUG_DIRECTORY_ENTRY.FileOffset. Tested with OVMF: - gcc-4.8.5-14.el7.x86_64 - binutils-2.25.1-27.base.el7.x86_64 and with ArmVirtPkg: - gcc-aarch64-linux-gnu-6.1.1-2.el7.x86_64 - binutils-aarch64-linux-gnu-2.27-3.el7.x86_64 Cc: Ard Biesheuvel Cc: Gerd Hoffmann Cc: Leif Lindholm Cc: Liming Gao Cc: Yonghong Zhu Reported-by: Gerd Hoffmann Reported-by: Leif Lindholm Ref: http://mid.mail-archive.com/a1de67a8-57c2-908e-dd4d-9726d60fb388@redhat.com Ref: http://mid.mail-archive.com/20170705134136.GB26676@bivouac.eciton.net Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- Notes: Repo: https://github.com/lersek/edk2.git Branch: binutils_debugdirsize_workaround BaseTools/Source/C/GenFw/GenFw.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c index 6569460f34f7..a79f485ee681 100644 --- a/BaseTools/Source/C/GenFw/GenFw.c +++ b/BaseTools/Source/C/GenFw/GenFw.c @@ -2771,6 +2771,7 @@ Returns: UINT32 Index; UINT32 DebugDirectoryEntryRva; UINT32 DebugDirectoryEntrySize; + UINT32 TruncatedDebugDirectorySize; UINT32 DebugDirectoryEntryFileOffset; UINT32 ExportDirectoryEntryRva; UINT32 ExportDirectoryEntryFileOffset; @@ -2893,6 +2894,25 @@ Returns: DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset); Index = 0; for (Index=0; Index < DebugDirectoryEntrySize / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) { + // + // Work around GNU Binutils bug: if the debug information pointed-to by + // DebugEntry was incorrectly included in DebugDirectoryEntrySize, then + // the debug directory doesn't actually extend past the pointed-to debug + // information. Truncate DebugDirectoryEntrySize accordingly. + // + if (DebugEntry->FileOffset >= DebugDirectoryEntryFileOffset && + DebugEntry->FileOffset < (DebugDirectoryEntryFileOffset + + DebugDirectoryEntrySize)) { + TruncatedDebugDirectorySize = (DebugEntry->FileOffset - + DebugDirectoryEntryFileOffset); + VerboseMsg ( + "truncating debug directory size from %u to %u", + DebugDirectoryEntrySize, + TruncatedDebugDirectorySize + ); + DebugDirectoryEntrySize = TruncatedDebugDirectorySize; + } + DebugEntry->TimeDateStamp = 0; if (ZeroDebugFlag || DebugEntry->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData); -- 2.13.1.3.g8be5a757fa67