From: "Laszlo Ersek" <lersek@redhat.com>
To: Roman Kagan <rkagan@virtuozzo.com>, devel@edk2.groups.io
Subject: Re: [edk2-devel] static data in dxe_runtime modules
Date: Sat, 3 Aug 2019 04:03:04 +0200 [thread overview]
Message-ID: <8d18d4f6-5f33-44e9-2758-46350b43c5ec@redhat.com> (raw)
In-Reply-To: <20190801191621.GB14235@rkaganb.sw.ru>
On 08/01/19 21:16, Roman Kagan wrote:
> I'm trying to come up with a solution to the problem that OpenSSL
> internally uses static variables ("per-thread" in no-threads config) to
> store pointers, which remain unadjusted upon SetVirtualAddressMap and
> cause the guest OS crash.
>
> More specifically, trying to set a signed variable leads to the
> following call chain:
>
> VariableServiceSetVariable
> ProcessVarWithPk
> VerifyTimeBasedPayloadAndUpdate
> Pkcs7GetSigners
> ASN1_item_d2i
> asn1_item_embed_d2i
> asn1_template_ex_d2i
> asn1_template_noexp_d2i
> asn1_item_embed_d2i
> asn1_template_ex_d2i
> asn1_template_noexp_d2i
> asn1_item_embed_d2i
> asn1_template_ex_d2i
> asn1_template_noexp_d2i
> asn1_item_embed_d2i
> pubkey_cb
> ERR_set_mark
> ERR_get_state
>
> The latter performs one-time initialization if needed, and then returns
> a pointer maintained in a static array using CRYPTO_THREAD_get_local().
> If a signed variable is set before SetVirtualAddressMap and (another
> one) after it, the pointer is initialized while in the old mapping and
> dereferenced while in the new one, crashing the OS.
>
> The real-world reproducer: install Windows Server 2016 in a VM with
> OVMF, shut it down, replace the varstore with a fresh template copy,
> boot Windows, try to update, say, "dbx" from within Windows => BSOD.
> The reason is that the Windows bootloader stores a secure variable
> "CurrentPolicy" if it isn't there, triggering the above callchain while
> still in identity mapping.
> (This problem isn't widely noticed because during the installation the
> bootloader stores CurrentPolicy, but the OS is soon rebooted, before it
> attempts to update dbx; upon that CurrentPolicy remains in the varstore
> and on further boots the bootloader skips setting it.)
This is a serious bug. Thank you for reporting and analyzing it. Can you
file it in the TianoCore Bugzilla too, please?
I think it's of general interest; virtualization is one way to reproduce
it, but it's not exclusive. Loss or wipign of UEFI variables can occur
on physical hardware too.
I wonder how far in OpenSSL history this issue goes back. Is this a
regression from the latest OpenSSL rebase in edk2?
> What would be the best way to fix it?
>
> One option is to audit OpenSSL and make sure it either doesn't put
> pointers into static storage or properly cleans them up (and call the
> cleanup function in RuntimeCryptLibAddressChangeEvent); then assume the
> rest of EDKII code is safe in this regard.
>
> Another is to assume that no static data in dxe_runtime modules should
> survive SetVirtualAddressMap, and thus make
> PeCoffLoaderRelocateImageForRuntime reinitialize the modules from
> scratch instead of re-applying the relocations only.
>
> I must admit I don't yet quite understand the full consequences of
> either option. Perhaps there are better ones.
> Any suggestion is appreciated.
If the runtime driver remembers pointer *values* from before
SetVirtualAddressMap() -- i.e. it saves pointer values into some
storage, for de-referencing at OS runtime --, those stored values have
to be converted in the virtual address change event notification function.
If your runtime driver says
Ptr = &mGlobalVariable;
Ptr->Field = 1;
at runtime, you don't have to do anything. If your driver says
mPtr = &mGlobalVariable;
at boot time, and then at OS runtime it does
mPtr->Field = 1;
then "mPtr" has to be converted, with EfiConvertPointer() in
"MdePkg/Library/UefiRuntimeLib/RuntimeLib.c".
PE/COFF massaging is unneeded.
The "thread_local_storage" array from
"CryptoPkg/Library/OpensslLib/openssl/crypto/threads_none.c" has to be
exposed to RuntimeCryptLibAddressChangeEvent() somehow.
Perhaps OpenSSL should allow edk2 to bring its own CRYPTO_THREAD_* APIs.
Thanks
Laszlo
next prev parent reply other threads:[~2019-08-03 2:03 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-01 19:16 static data in dxe_runtime modules Roman Kagan
2019-08-02 23:54 ` [edk2-devel] " Andrew Fish
2019-08-03 2:03 ` Laszlo Ersek [this message]
2019-08-05 10:18 ` Roman Kagan
2019-08-07 17:29 ` Laszlo Ersek
2019-08-07 17:41 ` Andrew Fish
2019-08-08 17:39 ` Laszlo Ersek
2019-08-09 16:07 ` Roman Kagan
[not found] ` <15B94CD6CF07DEE2.13696@groups.io>
2019-08-12 18:43 ` Roman Kagan
2019-08-13 9:10 ` Laszlo Ersek
2019-08-13 11:23 ` Roman Kagan
2019-08-14 15:16 ` Laszlo Ersek
2019-08-14 16:26 ` Andrew Fish
2019-08-16 15:22 ` Laszlo Ersek
2019-08-16 17:00 ` Roman Kagan
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=8d18d4f6-5f33-44e9-2758-46350b43c5ec@redhat.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