From: "Marc-André Lureau" <marcandre.lureau@gmail.com>
To: Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel@lists.01.org, Jiewen Yao <jiewen.yao@intel.com>,
Star Zeng <star.zeng@intel.com>,
Chao Zhang <chao.b.zhang@intel.com>
Subject: Re: [PATCH 1/1] RFC: SecurityPkg: only clear HashInterface informations
Date: Wed, 7 Mar 2018 11:53:41 +0100 [thread overview]
Message-ID: <CAJ+F1C+XsGXfyNti4r8Oz0izJNHhRUEq-tJTVHMi6_9LUOidZA@mail.gmail.com> (raw)
In-Reply-To: <1dbffca1-c83e-0839-45b5-62875b0cfae0@redhat.com>
Hi
On Wed, Mar 7, 2018 at 10:06 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> Hi Marc-André,
>
> On 03/06/18 21:27, marcandre.lureau@redhat.com wrote:
>> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>>
>> The ZeroMem() call goes beyond the HashInterfaceHob structure, causing
>> HOB list corruption. Instead, just clear the HashInterface fields, as
>> I suppose was originally intended.
>>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Chao Zhang <chao.b.zhang@intel.com>
>> Cc: Star Zeng <star.zeng@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>> .../HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> index dbee0f2531bc..361a4f6508a0 100644
>> --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> @@ -424,7 +424,8 @@ HashLibBaseCryptoRouterPeiConstructor (
>> // This is the second execution of this module, clear the hash interface
>> // information registered at its first execution.
>> //
>> - ZeroMem (&HashInterfaceHob->HashInterface, sizeof (*HashInterfaceHob) - sizeof (EFI_GUID));
>> + ZeroMem (&HashInterfaceHob->HashInterface, sizeof (HashInterfaceHob->HashInterface));
>> + HashInterfaceHob->HashInterfaceCount = 0;
>> }
>>
>> //
>>
>
> Excellent catch! :)
>
> I do have a question however, for the other reviewers on this patch, in
> line with your commit message saying, "clear the HashInterface fields,
> as *I suppose* was originally intended".
>
> I don't think the proposed update matches the original intent 100%.
> Namely, this is the definition of the HASH_INTERFACE_HOB type (from the
> same source file):
>
>> typedef struct {
>> //
>> // If gZeroGuid, SupportedHashMask is 0 for FIRST module which consumes HashLib
>> // or the hash algorithm bitmap of LAST module which consumes HashLib.
>> // HashInterfaceCount and HashInterface are all 0.
>> // If gEfiCallerIdGuid, HashInterfaceCount, HashInterface and SupportedHashMask
>> // are the hash interface information of CURRENT module which consumes HashLib.
>> //
>> EFI_GUID Identifier;
>> UINTN HashInterfaceCount;
>> HASH_INTERFACE HashInterface[HASH_COUNT];
>> UINT32 SupportedHashMask;
>> } HASH_INTERFACE_HOB;
>
> Note that it says, if Identifier equals "gEfiCallerIdGuid", then *all
> three* subsequent fields carry information of the current module that
> consumes HashLib. Those three fields include "SupportedHashMask".
>
> Furthermore, the comment just preceding the bug / ZeroMem() call says,
>
>> //
>> // In PEI phase, some modules may call RegisterForShadow and will be
>> // shadowed and executed again after memory is discovered.
>> // This is the second execution of this module, clear the hash interface
>> // information registered at its first execution.
>> //
>
> And note that here we are just past the check
>
>> HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
>> if (HashInterfaceHob != NULL) {
>
> in other words, the "Identifier equals gEfiCallerIdGuid" branch from the
> type definition applies; meaning that "SupportedHashMask" is defined
> too.
>
> Thus, I'd like the other reviewers to confirm whether we should clear
> "SupportedHashMask".
>
> From the original (buggy) code, I think we *should* clear
> SupportedHashMask as well. The "Length" argument of the original
> ZeroMem() call implies precisely that:
>
> sizeof (*HashInterfaceHob) - sizeof (EFI_GUID)
>
> This stands for "all fields in *HashInterfaceHob except the leading
> EFI_GUID Identifier field".
>
> So, the actual bug is in the "Buffer" argument of the ZeroMem() call: it
> is a typo. Certainly the intent must have been "start clearing from the
> first field right after the EFI_GUID Identifier field", namely
> "HashInterfaceCount":
>
> &HashInterfaceHob->HashInterfaceCount
> ^^^^^
>
> Therefore I think the *first* approach to actually fixing this bug would
> be to simply add the "Count" suffix:
>
>> diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> index dbee0f2531bc..a869fffae3fe 100644
>> --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> @@ -424,7 +424,10 @@ HashLibBaseCryptoRouterPeiConstructor (
>> // This is the second execution of this module, clear the hash interface
>> // information registered at its first execution.
>> //
>> - ZeroMem (&HashInterfaceHob->HashInterface, sizeof (*HashInterfaceHob) - sizeof (EFI_GUID));
>> + ZeroMem (
>> + &HashInterfaceHob->HashInterfaceCount,
>> + sizeof (*HashInterfaceHob) - sizeof (EFI_GUID)
>> + );
>> }
>>
>> //
>
> On the other hand, I don't think such a fix would be great. First of
> all, the HASH_INTERFACE_HOB struct definition is not wrapped in
>
> #pragma pack (1)
> ...
> #pragma pack ()
>
> in other words, HASH_INTERFACE_HOB is not packed, hence there could be
> an unspecified amount of padding between "Identifier" and
> "HashInterfaceCount". That would lead to the same kind of buffer
> overflow, because "Length" includes the padding, but the "Buffer"
> argument doesn't.
>
> Second, even if there were no padding (and thus the byte count would be
> a perfect match for the full HOB structure), in the "Buffer" argument
> we take the address of the "HashInterfaceCount" field, and with the
> "Length" field, we still overflow that *individual* field. Although we
> wouldn't overflow the containing HOB structure, this is still (arguably)
> undefined behavior -- I seem to remember that some compilers actually
> blow up on this when you use the standard ISO C memcpy() or memset()
> functions in such contexts.
>
> So, long story short, I suggest the following fix instead:
>
>> diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> index dbee0f2531bc..84c1aaae70eb 100644
>> --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
>> @@ -397,6 +397,7 @@ HashLibBaseCryptoRouterPeiConstructor (
>> {
>> EFI_STATUS Status;
>> HASH_INTERFACE_HOB *HashInterfaceHob;
>> + UINTN ClearStartOffset;
>>
>> HashInterfaceHob = InternalGetHashInterfaceHob (&gZeroGuid);
>> if (HashInterfaceHob == NULL) {
>> @@ -424,7 +425,11 @@ HashLibBaseCryptoRouterPeiConstructor (
>> // This is the second execution of this module, clear the hash interface
>> // information registered at its first execution.
>> //
>> - ZeroMem (&HashInterfaceHob->HashInterface, sizeof (*HashInterfaceHob) - sizeof (EFI_GUID));
>> + ClearStartOffset = OFFSET_OF (HASH_INTERFACE_HOB, HashInterfaceCount);
>> + ZeroMem (
>> + (UINT8 *)HashInterfaceHob + ClearStartOffset,
>> + sizeof (*HashInterfaceHob) - ClearStartOffset
>> + );
>> }
>>
>> //
>
> Thoughts?
Looking at RegisterHashInterfaceLib() code, I agree it makes sense to
clear both the array and the mask. Both seem to be closely related
during registration.
I agree with your argument as well about structure packing. I'll
resend the patch with your suggested changes.
thanks
prev parent reply other threads:[~2018-03-07 10:47 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-06 20:27 [PATCH 1/1] RFC: SecurityPkg: only clear HashInterface informations marcandre.lureau
2018-03-07 0:40 ` Zeng, Star
2018-03-07 0:40 ` Yao, Jiewen
2018-03-07 2:03 ` Zhang, Chao B
2018-03-07 9:06 ` Laszlo Ersek
2018-03-07 9:42 ` Zeng, Star
2018-03-07 15:05 ` Zeng, Star
2018-03-07 20:50 ` Laszlo Ersek
2018-03-07 10:53 ` Marc-André Lureau [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAJ+F1C+XsGXfyNti4r8Oz0izJNHhRUEq-tJTVHMi6_9LUOidZA@mail.gmail.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox