rhboot / shim

UEFI shim loader
Other
819 stars 289 forks source link

Possible regression: 2021.08.12 shim boots whereas 2023.01.18 freezes in a chain-loaded Secure Boot context #558

Closed pbatard closed 1 year ago

pbatard commented 1 year ago

Issue description

It appears that, when running in a Secure Boot environment, the current shim introduced a regression, that is currently manifesting itself and affecting users trying to create NTFS-based boot media from Ubuntu Studio 22.04.2 LTS (this was tested with ubuntustudio-22.04.2-dvd-amd64.iso) when using the NTFS chain loader from the Rufus boot media creation utility.

Basically, because the Ubuntu ISO contains a file that is larger than 4 GB, Rufus extracts the ISO content onto an NTFS partition rather than a FAT32 partition (since FAT cannot accommodate files larger than 4 GB) and then, for UEFI systems that do not have a native NTFS driver, chains load the Red Hat Shim from a small additional FAT partition that contains a UEFI boot loader that can load a UEFI NTFS driver and then hands of boot to the NTFS-residing bootloaders.

This chain loader, called UEFI:NTFS is itself Secure Boot signed, along with its read-only NTFS driver that is derived from ntfs-3g. Note that this driver was restricted to read-only as a means to improve its resilience against potential vulnerabilities and therefore facilitate the Secure Boot validation process.

However, we have recently found out that, when Secure Boot is active (the issue does not manifest itself when Secure Boot is Disabled or in Setup mode), the process above appears to freeze during shim execution when using the 2023.01.18 Secure Boot signed version. Yet, when replacing the shim with a 2021.08.12 Secure Boot signed version, everything works as expected.

Thus, it would appear that a regression was introduced between 2021.07 and 2023.01.18 that causes a freezout when shim is chain loaded from a read-only NTFS partition.

Steps to replicate

The attached shim.zip contains a 8 MB uncompressed VHD disk image, which, for all intents and purposes will work the same as a dd disk image (since uncompressed VHD = regular disk image + 512 bytes footer), that you should be able to use with any USB disk media to recreate a test disk that includes:

Thus, if you dd write that image, you will end up with a GPT partitioned bootable drive can be used to replicate the issue.

From there, you should to test this drive on a UEFI based system that meets the following two conditions:

  1. Has Secure Boot enabled.
  2. Does NOT natively include a NTFS driver (more about this below).

On such a system, and provided that your UEFI firmware isn't pedantic about the fact that the backup GPT of the drive you just created will be invalid (which most firmwares will happily ignore), you should end up with a screen similar to the one below, indicating, after providing some info about your system, first, that the NTFS driver was successfully loaded, then that the shim was successfully located on the NTFS partition and finally that the UEFI boot process has successfully been handed over to it:

C4ZEh

Then, provided that you can mount the NTFS partition from the drive you created, if you rename /efi/boot/bootx64.old to /efi/boot/bootx64.efi, you will find that the process does go past the screen above up to the stage where shim reports, as expected if the execution is working, that it could not locate grubx64.efi, which tend to support the idea that we are, in effect, dealing with a shim regression.

Note that the shim bootloaders used in this test image come from ubuntustudio-22.04.2-dvd-amd64.iso and ubuntu-22.10-desktop-amd64.iso, with the older one actually being from 22.10.

Investigation notes

pbatard commented 1 year ago

Further investigation has allowed me to conclude that this is a duplicate of the issue reported in #547, and especially the problem is that our NTFS driver is not specs compliant when it comes to EFI_FILE_PROTOCOL.Read() that states (in Section 13.5 File Protocol):

If This is a directory, the function reads the directory entry at the file’s current position and returns the entry in Buffer. If the Buffer is not large enough to hold the current directory entry, then EFI_BUFFER_TOO_SMALL is returned and (...) BufferSize is set to be the size of the buffer needed to read the entry.

As we were able to confirm, the root of the issue is that, when reading the efi/boot/ directory with BufferSize set to 0, the NTFS driver is returning 0 instead of the size of the buffer needed to read the entry, which leads pre 2023.02.01 Shim code to enter an infinite loop.

Obviously, we will fix the NTFS driver for compliance, to avoid the issue altogether, but it's nice to see that Shim has also taken steps to try to alleviate it.

pbatard commented 1 year ago

I have now confirmed that the latest shim (with the f23883ccf78f1f605a272f9e5700f47e5494a71d / #547 patch applied) does bail out when using the problematic driver instead of entering an infinite loop.

However, since I believe that the code from f23883ccf78f1f605a272f9e5700f47e5494a71d can be improved to progressively increase the buffer size in order to successfully complete the directory read, I have now submitted PR #560 that does just this.

vathpela commented 1 year ago

Can I close this?

pbatard commented 1 year ago

I will close this now, yes.

The issue was fixed in the NTFS driver and with the commit that was integrated in Shim, there is no reason to have this issue opened.

Thanks again!