Skip to content

Comments

Add support for UEFI signing, SBAT signature revocations, and NX mitigations.#34

Merged
x86fr merged 7 commits intomemtest86plus:mainfrom
vathpela:uefi-signing-and-sbat
Jan 2, 2023
Merged

Add support for UEFI signing, SBAT signature revocations, and NX mitigations.#34
x86fr merged 7 commits intomemtest86plus:mainfrom
vathpela:uefi-signing-and-sbat

Conversation

@vathpela
Copy link
Contributor

@vathpela vathpela commented Apr 5, 2022

(This is not yet ready)

In order to facilitate adoption by major linux distributions, memtest86+ EFI builds are going to need to support Authenticode signatures and the SBAT revocation method, and will eventually need to support being loaded with NX (W^X) vulnerability mitigations enabled.

This patch series aims to add all of those, though right now it doesn't work correctly on some UEFI firmware builds, and I'm still debugging, so there are some extra patches here that won't be necessary once I'm ready to propose it upstream.

@debrouxl
Copy link
Collaborator

debrouxl commented Apr 5, 2022

Whoa, thanks for this draft contribution :)

It shall help with #25 when merged.

@x86fr x86fr requested a review from martinwhitaker April 6, 2022 00:09
@x86fr
Copy link
Member

x86fr commented Apr 6, 2022

Thanks Peter, this is greatly appreciated 😍

Copy link
Collaborator

@martinwhitaker martinwhitaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know why you need to add /boot/ in .gitignore - it's already ignored on my system (because all the files it contains are in the ignore list). Maybe git behaviour has changed.

Copy link
Collaborator

@martinwhitaker martinwhitaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding boot/peimage.h will also require updating the top level LICENSE file. Currently all files in the project are GPL 2 only.

@martinwhitaker
Copy link
Collaborator

We don't need to load at 0x200000, but we do need to load at an address < 3GB (preferably < 2GB). I don't know any way to achieve that other than specifying a fixed address. To keep the program memory footprint low, we set up the paging tables to only use the first 4GB of virtual memory space. We use the space between 2GB and 3GB when testing memory, and we use the space between 3GB and 3.5GB to provide permanent access to memory mapped hardware and the frame buffer. So if we allow the EFI loader to load the program anywhere in physical memory, we would have to be prepared to to relocate it.

@vathpela
Copy link
Contributor Author

Adding boot/peimage.h will also require updating the top level LICENSE file. Currently all files in the project are GPL 2 only.

I'm pretty sure I can find a GPLv2 version of it, let me look around a bit.

@vathpela vathpela force-pushed the uefi-signing-and-sbat branch from 10e06f8 to 8e07a47 Compare April 13, 2022 21:09
@vathpela
Copy link
Contributor Author

vathpela commented Apr 13, 2022

We don't need to load at 0x200000, but we do need to load at an address < 3GB (preferably < 2GB). I don't know any way to achieve that other than specifying a fixed address. To keep the program memory footprint low, we set up the paging tables to only use the first 4GB of virtual memory space. We use the space between 2GB and 3GB when testing memory, and we use the space between 3GB and 3.5GB to provide permanent access to memory mapped hardware and the frame buffer. So if we allow the EFI loader to load the program anywhere in physical memory, we would have to be prepared to to relocate it.

Is relocating it an option you'd be okay with? I am able to contribute relocation code... That said, I may be able to just drop that patch; it's mostly there right now to make comparing two VMs with different firmware easier.

@martinwhitaker
Copy link
Collaborator

Relocating is okay, and is already supported - the program regularly relocates itself whilst the tests are running to allow the memory it occupies to be tested. So it should just be a matter of scanning the E820 memory map to find a suitable location, copying the program code and data sections, and contriving to return from efi_setup() to the relocated address. The relocation fixups will be done by the startup code.

I just wasn't going to bother doing that unless it was found to be needed.

@x86fr x86fr mentioned this pull request May 10, 2022
@vathpela vathpela force-pushed the uefi-signing-and-sbat branch from 8e07a47 to f8d88aa Compare May 10, 2022 15:12
@x86fr x86fr added the enhancement New feature or request label May 22, 2022
@x86fr x86fr linked an issue May 22, 2022 that may be closed by this pull request
@x86fr
Copy link
Member

x86fr commented Jun 12, 2022

@vathpela Is there something we can do to help?

@01e3
Copy link
Contributor

01e3 commented Aug 21, 2022

Hi there.

Just checking what is the plan here?

The PR is currently marked as draft, how much work is left here?

Do we expect this can be merged early during 6.10 development?

This patch makes it so we use "gcc -x assembler-with-cpp" to build our
.S files, instead of translating them to .s files and assembling
directly.  This allows us to use header files and simple symbolic
arithmetic more conveniently in .S files, and at the same time reduces
the number of temporary files created when building.

Signed-off-by: Peter Jones <[email protected]>
This adds a header file to describe the PE binary we're building.  This
has constants defined for all the values we use in the PE headers, as
well as the structures for reference (guarded by #ifdef __ASSEMBLY__).

This particular peimage.h is originally from binutils-2.10.0.18, which
is GPLv2 licensed, and is copyright the Free Software Foundation.  I've
added the few additional fields we need.

Signed-off-by: Peter Jones <[email protected]>
This changes header.S to use the constants defined in peimage.h to for
the values in its structure, making it a lot easier to debug.

Signed-off-by: Peter Jones <[email protected]>
Currently, the PE headers we create in boot/header.S do not allocate
space for any Data Directory entries, as they haven't been needed.

In order to support signatures and compatibility with some loaders, we
need the Data Directory to be populated at least enough to set
DataDirectory.Certs and DataDirectory.BaseReloc.

This patch extends that space enough to include those entries.

Signed-off-by: Peter Jones <[email protected]>
SizeOfImage is defined as:

  The size (in bytes) of the image, including all headers, as the image
  is loaded in memory. It must be a multiple of SectionAlignment.

SizeOfHeaders likewise is defined as:

  The combined size of an MS-DOS stub, PE header, and section headers
  rounded up to a multiple of FileAlignment.

Currently SizeOfImage represents .bss and .text, but it doesn't include
.header or .setup, nor any sections we'll add later, and there's nothing
enforcing that it matches SectionAlignment.  Additionally, since .bss is
being set up in our running code and /not/ by the loader, the current
value is dangerously high, as in the event there is an error in the
section table, it could potentially lead the loader to mark memory
allocated at runtime holding user-supplied data by any EFI binary loaded
before us as executable.

This patch adds a new symbol, _img_end, which is after .text and is
rounded up to 4kB (which is also what SectionAlignment is set to).  It
also adds a local label, anchored with ".org 512", and uses that to set
SizeOfHeaders - this will ensure the build fails without outputting and
invalid binary if the headers take too much space.

Signed-off-by: Peter Jones <[email protected]>
In the past, we've seen some problems with some EFI loaders refusing to
load a binary that has both a .text section with the VMA set and no
relocations, when the VMA set to load is already allocated for some
other purpose.

This patch adds a dummy absolute relocation from 0 to 0, so the loader
can always feel like it has done something useful.

Signed-off-by: Peter Jones <[email protected]>
@vathpela vathpela force-pushed the uefi-signing-and-sbat branch from f8d88aa to 6dfd70e Compare October 25, 2022 20:14
@vathpela vathpela marked this pull request as ready for review October 25, 2022 20:16
@vathpela
Copy link
Contributor Author

vathpela commented Oct 25, 2022

I haven't had the time to debug whatever issue I'm hitting with this on QEMU, but it works on all of my real hardware, so I think that's probably not a good reason to hold this back, especially since there's little point in actually running memtest in QEMU. So I've removed the .gitignore patch that I was just carrying for my own creature comforts, as well as the patch to set the NX flag (because I was wrong and there's work to be done there), and marked it as ready for review.

This patch adds a new section, ".sbat", which allows for the revocation
of signed binaries given a numeric value representing the set of bugs
which allow for arbitrary code execution, and therefore a Secure Boot
breakout, in a given family of binaries.

In this case, the class is defined as "memtest86+", and the current set
of bugs is 1.  This doesn't imply that we're aware of bugs currently,
merely that when we change it to 2, any bugs that /have/ been discovered
have been fixed.

Documentation for how SBAT works can be found at the following URLs:

  https://github.com/rhboot/shim/blob/main/SBAT.md
  https://github.com/rhboot/shim/blob/main/SBAT.example.md

Signed-off-by: Peter Jones <[email protected]>
@vathpela vathpela force-pushed the uefi-signing-and-sbat branch from 6dfd70e to e35dae2 Compare October 25, 2022 21:21
@x86fr
Copy link
Member

x86fr commented Oct 25, 2022

Awesome! We will carefully review this PR then I'll put this in betatesters' hands as soon as possible.

@martinwhitaker
Copy link
Collaborator

This looks OK to me. I did use QEMU extensively for developing and debugging the USB drivers, but I'm not seeing any issues with it.

@x86fr
Copy link
Member

x86fr commented Nov 18, 2022

Betatesters found an issue with this PR on Asus 700-series motherboard. We're investigating the issue with their BIOS team. It seems linked to a specific ME.

@martinwhitaker
Copy link
Collaborator

I do note that now _bss_size is not included in SizeOfImage, I can't see that there is any guarantee that the bss section does not collide with memory reserved by the EFI BIOS (which is why I included it).

@x86fr
Copy link
Member

x86fr commented Nov 27, 2022

Info point: We found an issue (indirectly related) on ASUS motherboard BIOS based on 700-series Intel chipset that prevent testing of secureboot related code right now. The bug is serious as it lead to a firmware corruption with boot failure. It's only present on 0602 BIOS update. A beta fix has been sent by ASUS and successfully tested. Betatesters are now waiting for the final new BIOS to resume validation on SB.

@vathpela
Copy link
Contributor Author

vathpela commented Dec 2, 2022

Info point: We found an issue (indirectly related) on ASUS motherboard BIOS based on 700-series Intel chipset that prevent testing of secureboot related code right now. The bug is serious as it lead to a firmware corruption with boot failure. It's only present on 0602 BIOS update. A beta fix has been sent by ASUS and successfully tested. Betatesters are now waiting for the final new BIOS to resume validation on SB.

Am I right in understanding that we believe this is a bios bug?

@x86fr
Copy link
Member

x86fr commented Dec 11, 2022

Yes, this has been confirmed and solved by Asus. Unfortunately, the betatester team found in the meanwhile another (unrelated) critical bug on Asus motherboards that broke the validation process on the production line. They're now waiting for a fix to resume testing this PR.

@x86fr x86fr mentioned this pull request Dec 11, 2022
@x86fr x86fr added this to the Memtest86+ 6.10 milestone Dec 11, 2022
@x86fr
Copy link
Member

x86fr commented Jan 2, 2023

Got the the first preliminary report from betatesters. This PR has been tested on 50+ platforms with Secure Boot Enabled with great success! Thanks @vathpela! The only fails they got were on Intel NUCs (waiting for more details). I tested it myself on some motherboards and laptops without issues so far. It's time to merge!

@x86fr x86fr merged commit 04980df into memtest86plus:main Jan 2, 2023
@vathpela vathpela deleted the uefi-signing-and-sbat branch January 27, 2023 21:06
martinwhitaker added a commit that referenced this pull request Jan 31, 2023
When the reloc and sbat sections were added by PR #34, three bugs were
introduced:

1. The virtual address and size fields in the PE headers were set to the
same values as the raw address and size fields. This is incorrect, because
the sections in the image file are aligned on 512 byte boundaries, but when
loaded into memory they need to be aligned on 4096 byte boundaries.

2. The value programmed into the SizeOfImage field was too large, as it
double-counted the region before the start of the .text section.

3. The value programmed into the SizeOfImage field no longer included the bss
size. That potentially allowed the EFI loader to load the image immediately
before a reserved region of memory without leaving enough space for the bss
section.

This commit fixes those bugs by calculating both file and virtual memory
offsets & sizes in the ld script. Note that we can't add a bss section to the
EFI image because many EFI loaders fail to load images that have uninitialised
data sections. Instead the text region size in virtual memory is increased
to include the bss size.

This fixes issue #243. It also eliminates the gaps between sections
observed in issue #202.
x86fr pushed a commit that referenced this pull request Feb 2, 2023
When the reloc and sbat sections were added by PR #34, three bugs were
introduced:

1. The virtual address and size fields in the PE headers were set to the
same values as the raw address and size fields. This is incorrect, because
the sections in the image file are aligned on 512 byte boundaries, but when
loaded into memory they need to be aligned on 4096 byte boundaries.

2. The value programmed into the SizeOfImage field was too large, as it
double-counted the region before the start of the .text section.

3. The value programmed into the SizeOfImage field no longer included the bss
size. That potentially allowed the EFI loader to load the image immediately
before a reserved region of memory without leaving enough space for the bss
section.

This commit fixes those bugs by calculating both file and virtual memory
offsets & sizes in the ld script. Note that we can't add a bss section to the
EFI image because many EFI loaders fail to load images that have uninitialised
data sections. Instead the text region size in virtual memory is increased
to include the bss size.

This fixes issue #243. It also eliminates the gaps between sections
observed in issue #202.
@tenzap
Copy link

tenzap commented Jun 2, 2025

@vathpela , could you please have a look at #516 ?
There is I think a typo in your sbat, but even when I fix this, I have another "relocation" issue #516 (comment) (Case2) that I don't know how to address.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dealing with Secure Boot

6 participants