summaryrefslogtreecommitdiff
path: root/shim.c
AgeCommit message (Collapse)Author
2024-01-22Try to load revocations.efi even if directory read failsJan Setje-Eilers
Network booting tends to expose things like a tfpt server as a filesystem that doesn't implement directory listing This will blindly try to ingest a revocations.efi file in those cases, even if that may result in some console noise when the file does not exist. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2024-01-22netboot read_image() should not hardcode DEFAULT_LOADERJan Setje-Eilers
The netboot path up until now hardcodes DEFAULT_LOADER as the only possible filename to load. This is pretty limiting and needs to be fixed. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2024-01-22Rename "previous" revocations to "automatic"Jan Setje-Eilers
When the term previous was introduced for revocations to be automatically applied there was a hope that everytime a new revocation was built into shim, the previous revocation could be applied automatically. Further experience has shown the real world to be more complex than that. The automatic payload will realistically contain a set of revocations governed by both the cadence at which a distro's customer base updates as well as the severity of the issue being revoked. This is not a functional change. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2024-01-22Suppress "Failed to open <..>\revocations.efi" when file does not existJan Setje-Eilers
Attempting to call loadimage on revocations.efi when it isn't present should results in error messages being printed to the console on at least some firmware: Failed to open \EFI\distro\revocations.efi - Not Found Failed to load image ...: Not Found Of course this is going to be the normal case on nearly all systems, at least to begin with. Since we are about to loop through the directory entries anyway, we can just make two passes, first looking for revocations.efi and then looking for shim_certificate.efi. This will still ensure that any revocations in revocations.efi are picked up before shim_certificate.efi is loaded without resulting in any noise on the console. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2024-01-22Fix some minor ia32 build issues.Peter Jones
Several of our CVE fixes apparently were not well tested on 32-bit, and needed some (uintptr_t) casts sprinkled about to build with -Werror=pointer-to-int-cast. Signed-off-by: Peter Jones <pjones@redhat.com>
2023-12-05sbat revocations: check the full section namePeter Jones
Inline PE section names (i.e. when not using the string table) are 8 byte arrays. They often look like ASCII strings, but they are not ASCII strings. This patch changes load_revocations_file() to always check that the full array matches the section name in question. Signed-off-by: Peter Jones <pjones@redhat.com>
2023-12-05shim should not self revokeJan Setje-Eilers
Before applying an updated SbatLevel shim should re-run introspection and never apply a revocation level that would prevent the currently running shim from booting. The proper way forward is to update shim first. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2023-12-05BS Variables for bootmgr revocationsJan Setje-Eilers
This adds support for applying SkuSiPolicy UEFI BS variables. These varaibles are needed for non-dbx based Windows revocations and are described here: https://support.microsoft.com/en-us/topic/kb5027455-guidance-for-blocking-vulnerable-windows-boot-managers-522bb851-0a61-44ad-aa94-ad11119c5e91 Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2023-12-05Allow SbatLevel data from external binaryJan Setje-Eilers
Ingest SBAT Levels from revocations binary thereby allowing level requirements to be updated independently from shipping a new shim. Do not automatically apply any revocations from a stock shim at this point. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2023-12-05CVE-2023-40548 Fix integer overflow on SBAT section size on 32-bit systemPeter Jones
In verify_sbat_section(), we do some math on data that comes from the binary being verified - in this case, we add 1 to the size of the ".sbat" section as reported in the section header, which is then used as the input to the size of an allocation. The original value is then used for a size in a memcpy(), which means there's an out-of-bounds write in the overflow case. Due to the type of the variable being size_t, but the type in the section header being uint32_t, this is only plausibly accomplished on 32-bit systems. This patch makes the arithmetic use a checked add operation to avoid overflow. Additionally, it adds a check in verify_buffer_sbat() to guarantee that the data is within the binary. It's not currently known if this is actually exploitable on such systems; the memory layout on a particular machine may further mitigate this scenario. Resolves: CVE-2023-40548 Reported-by: gkirkpatrick@google.com Signed-off-by: Peter Jones <pjones@redhat.com>
2023-12-05CVE-2023-40549 Authenticode: verify that the signature header is in bounds.Peter Jones
In the validation logic in verify_buffer_authenticode(), there is yet another case where we need to guarantee an object is in the binary but we're only validating the pointer to it. In this case, we're validating that the actual signature data is in the binary, but unfortunately we failed to validate that the header describing it is, so a malformed binary can cause us to take an out-of-bounds read (probably but not necessarily on the same page) past the end of the buffer. This patch adds a bounds check to verify that the signature is actually within the bounds. It seems unlikely this can be used for more than a denial of service, and if you can get shim to try to verify a malformed binary, you've effectively already accomplished a DoS. Resolves: CVE-2023-40549 Reported-by: gkirkpatrick@google.com Signed-off-by: Peter Jones <pjones@redhat.com>
2023-12-05CVE-2023-40550 pe: Fix an out-of-bound read in verify_buffer_sbat()Peter Jones
In verify_buffer_sbat(), we have a goal-seeking loop to find the .sbat section header. Unfortunately, while the actual contents of the section are checked for being inside the binary, no such check exists for the contents of the section table entry. As a result, a carefully constructed binary will cause an out-of-bounds read checking if the section name is ".sbat\0\0\0" or not. This patch adds a check that each section table entry is within the bounds of the binary. It's not currently known if this is actually exploitable beyond creating a denial of service, and an attacker who is in a position to use it for a denial of service attack must already be able to do so. Resolves: CVE-2023-40550 Reported-by: gkirkpatrick@google.com Signed-off-by: Peter Jones <pjones@redhat.com>
2023-06-27Verify signature before verifying sbat levelsJan Setje-Eilers
Verifying the validity of a files signature can protect from an attacker creating a file that exploits a potential issue in the sbat validation. If the signature is not checked first, an attacker can just create a file with a valid .sbat section and can still attack the signature validation. Signed-off-by: Jan Setje-Eilers <Jan.SetjeEilers@oracle.com>
2023-06-21Rename 'msecs' to 'usecs' to avoid potential confusionKamil Aronowski
The function msleep uses gBS->Stall which waits for a specified number of microseconds. Reference: https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/5_uefi_services/51_services_that_uefi_drivers_commonly_use/517_stall This reference even mentions an example sleeping for 10 microseconds: // Wait 10 uS. Notice the letter 'u'. Therefore it's a good idea to call the function 'usleep' rather than 'msleep', so no one confuses it with milliseconds, and to change the argument name to match as well. Signed-off-by: Kamil Aronowski <kamil.aronowski@yahoo.com>
2023-05-02Further improve load_certs() for non-compliant drivers/firmwaresPete Batard
Following the discovery of more problematic firmwares and drivers affected by the issue f23883ccf78f1f605a272f9e5700f47e5494a71d is designed to address (e.g. https://github.com/rhboot/shim/issues/558), this patch further improves the code so that, instead of simply bailing out, we progressively increase the buffer sizes, until either success or a maximum size limit is reached. In most cases, this workaround should be enough to ensure completion of the directory read and thus provide full shim functionality (while still warning the user about the non-compliance of their environment). Signed-off-by: Pete Batard <pete@akeo.ie>
2023-05-02Drop invalid calls to `CRYPTO_set_mem_functions`Nicholas Bishop
These calls did not check the return value. If they had, it would have shown that the calls were failing due to passing `NULL` for the `realloc` function pointer. That causes an early return, so the calls weren't actually doing anything. The `malloc`/`realloc`/`free` functions defined in Cryptlib/SysCall/BaseMemAllocation.c are what actually get used, so just drop the explicit call to `CRYPTO_set_mem_functions`. Signed-off-by: Nicholas Bishop <nicholasbishop@google.com>
2023-05-02Optionally allow to keep shim protocol installedLuca Boccassi
If the ShimRetainProtocol variable is set, avoid uninstalling our protocol. For example, this allows sd-stub in a UKI to use the shim protocol to validate PE binaries, even if it is executed by a second stage, before the kernel is loaded. Ensure that the variable is volatile and for BootServices access. Also delete it on startup, so that we can be sure it was really set by a second stage. Example use case in sd-boot/sd-stub: https://github.com/systemd/systemd/pull/27358 Signed-off-by: Luca Boccassi <bluca@debian.org>
2023-02-01Don't loop forever in load_certs() with buggy firmwareRenaud Métrich
On DELL R350 booting DVD through RFS with BIOS 1.4.2 in Secure Boot, firmware returns EFI_BUFFER_TOO_SMALL but with new buffersize set to 0, which causes the load_certs() code to loop forever: while (1) { efi_status = dir->Read(dir, &buffersize, buffer); if (efi_status == EFI_BUFFER_TOO_SMALL) { ... continue; } ... } This commit prevents such infinite loop. Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
2022-11-08load_cert_file: Use EFI RT memory functionEric Snowberg
Use the EFI RT memory function CopyMem instead of memcpy in load_cert_file. Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
2022-11-08load_cert_file: Fix stack issueEric Snowberg
0214cd9cef5a fixes a NULL pointer dereference problem, it introduces two new problems. First it incorrectly assumes li.FilePath is a string. Second, it puts EFI_LOADED_IMAGE li on the stack. It has been found that not all archectures can handle this being on the stack. The shim_li variable will be setup properly from the read_image call. Use the global shim_li variable instead when calling verify_image. Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
2022-08-03Reference MokListRT instead of MokListEric Snowberg
When calling back into shim from grub, the MokListRT may contain additional entries not available in the original MokList, an example being the certs included via user_cert. Use the MokListRT instead when calling check_db_cert and check_db_hash. Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
2022-05-23load_cert_file(): don't defererence NULLPeter Jones
Coverity noticed that the refactoring of handle_image() wildly misunderstood how we deal with file paths. This reworks it to not have a bunch of NULL dereferences. Signed-off-by: Peter Jones <pjones@redhat.com>
2022-05-18load_certs: trust dir->Read() slightly less.Peter Jones
scan-build says info->FileName returned from a successful call to dir->Read() can be NULL. I don't think that would be a compliant implementation, but anything's possible. This patch checks it for NULL-ness before the StrCaseCmp(). Signed-off-by: Peter Jones <pjones@redhat.com>
2022-05-18Always initialize data/datasize before calling read_image()Peter Jones
scan-build noticed that there's a path where we'll pass some data from the read_image() to e.g. the string functions, but it might be an unassigned pointer on one of the code paths. I don't think you can actually hit it without returning from an error first, but best to initialize these anyway. This patch initializes data to NULL and datasize to 0. Signed-off-by: Peter Jones <pjones@redhat.com>
2022-05-17Load additional certs from a signed binaryEric Snowberg
Heavily inspired by Matthew Garrett's patch "Allow additional certificates to be loaded from a signed binary". Add support for loading a binary, verifying its signature, and then scanning it for embedded certificates. This is intended to make it possible to decouple shim builds from vendor signatures. In order to add new signatures to shim, an EFI Signature List should be generated and then added to the .db section of a well-formed EFI binary. This binary should then be signed with a key that shim already trusts (either a built-in key, one present in the platform firmware or one present in MOK) and placed in the same directory as shim with a filename starting "shim_certificate" (eg, "shim_certificate_oracle"). Shim will read multiple files and incorporate the signatures from all of them. Note that each section *must* be an EFI Signature List, not a raw certificate. Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
2022-05-17Abstract out image readingEric Snowberg
Separate out image reading from image launch in order to be able to load an image without executing it. Signed-off-by: Matthew Garrett <mgarrett@aurora.tech> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
2022-05-17shim: use SHIM_DEVEL_VERBOSE when built in devel modePeter Jones
This makes SHIM_VERBOSE / SHIM_DEVEL_VERBOSE work the same way as SHIM_DEBUG / SHIM_DEVEL_DEBUG when shim is built with ENABLE_SHIM_DEVEL set. Signed-off-by: Peter Jones <pjones@redhat.com>
2022-04-05shim: implement SBAT verification for the shim_lock protocolChris Coulson
This implements SBAT verification via the shim_lock protocol by moving verification inside the existing verify_buffer() function that is shared by both shim_verify() and handle_image(). The .sbat section is optional for code verified via the shim_lock protocol, unlike for code that is verified and executed directly by shim. For executables that don't have a .sbat section, verification is skipped when using the protocol. A vendor can enforce SBAT verification for code verified via the shim_lock protocol by revoking all pre-SBAT binaries via a dbx update or by using vendor_dbx and then only signing binaries that have a .sbat section from that point. Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
2021-12-10shim: Don't stop forever at "Secure Boot not enabled" notificationRenaud Métrich
Requesting a keystroke when Secure Boot is not enabled and verbosity is enabled is really annoying. Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
2021-10-12shim: Don't parse load options if invoked from removable media pathJulian Andres Klode
We see various reports of boot failures because the generated boot entries contain garbage/tagging that we do not expect, and that we then parse as a second stage boot loader.
2021-10-12Extract is_removable_media_path() out of should_use_fallback()Julian Andres Klode
Simple refactoring that extracts the path checking on the given loaded image. This will be useful to check if we were booted via removable media path in other places.
2021-09-14Fallback to default loader if parsed one does not existJulian Andres Klode
If the specified second stage loader does not exist (invalid parameter), fall back to the DEFAULT_LOADER. This avoids failing the boot on any garbage that made it through the load option parser as a second stage loader name. Bug-Ubuntu: https://bugs.launchpad.net/bugs/1937115
2021-09-07shim/mm/fb: move global state to its own source filePeter Jones
This moves the globals from shim.c (and lib/console.c) into their own file, to make it so that unit tests can more easily link against code that uses that state. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-09-07cleanup: always use BS and RT, not gBS and gRTPeter Jones
This just makes one less thing we have to make sure is the same between the test harnesses and the runtime code. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-09-03shim: avoid BOOTx64.EFI in message on other architecturesHeinrich Schuchardt
An error message complaining about missing file BOOTx64.EFI makes no sense on other architectures. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2021-07-20shim: move the bulk of set_second_stage() to its own filePeter Jones
This moves set_second_stage() and some of the helper functions it uses out of shim.c, so that it's easier to write test cases for. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-07-20shim: rename pause() to wait_for_debug()Peter Jones
pause() is a posix function, and having it named the same as this makes it hard to include the asm.h header in some test cases. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-07-20shim: another attempt to fix load options handlingChris Coulson
The load options handling is quite complicated and tries to accomodate several scenarios, but there are currently multiple issues: - If the supplied LoadOptions is an EFI_LOAD_OPTION structure, second_stage gets initialized to the entire contents of the OptionalData field and load_options is initialized to NULL, which means it isn't possible to pass additional options to the second stage loader (and it looks like the intention is for this to be supported). - If the supplied LoadOptions contains 2 or more strings, the code seems to assume that shim was executed from the UEFI shell and that the first argument is the path of the shim executable, so it's ignored. But this breaks the ability to pass additional options to the second stage loader from BDS on firmware implementations that initialize LoadOptions to just the OptionalData field of the EFI_LOAD_OPTION, which is what EDK2 seems to do. This is moot anyway because this case (strings == 2) doesn't actually seem to work, as nothing sets loader_len and therefore second_stage is not set to the custom loader path. - If the supplied LoadOptions contains a single string that isn't shim's path, nothing sets loader_len and therefore second_stage isn't set at the end of set_second_stage. - set_second_stage replaces L' ' characters with L'\0' - whilst this is useful to NULL terminate the path for the second stage, it doesn't seem quite right to do this for the remaining LoadOptions data. Grub's chainloader command supplies additional arguments as a NULL-terminated space-delimited string via LoadOptions. Making it NULL-delimited seems to be incompatible with the kernel's commandline handling, which wouldn't work for scenarios where you might want to direct-boot a kernel image (wrapped in systemd's EFI stub) from shim. - handle_image passes the original LoadOptions to the second stage if load_options is NULL, which means that the second stage currently always gets shim's load options. I've made an attempt to try to fix things. After the initial checks in set_second_stage, it now does this: - Tries to parse LoadOptions as an EFI_LOAD_OPTION in order to extract the OptionalData if it is. - If it's not an EFI_LOAD_OPTION, check if the first string is the current shim path and ignore it if it is (the UEFI shell case). - Split LoadOptions in to a single NULL terminated string (used to initialize second_stage) and the unmodified remaining data (used to initialize load_options and load_options_size). I've also modified handle_image to always set LoadOptions and LoadOptionsSize. If shim is executed with no options, or is only executed with a single option to override the second stage loader path, the second stage is executed with LoadOptions = NULL and LoadOptionsSize = 0 now. I've tested this on EDK2 and I can load a custom loader with extra options from both BDS and the UEFI shell: FS0:\> shimx64.efi test.efi LoadOptionsSize: 0 LoadOptions: (null) FS0:\> shimx64.efi test.efi LoadOptionsSize: 0 LoadOptions: (null) FS0:\> shimx64.efi test.efi foo bar LoadOptionsSize: 16 LoadOptions: foo bar
2021-06-23Relax the check for import_mok_state()Gary Lin
An openSUSE user reported(*) that shim 15.4 failed to boot the system with the following message: "Could not create MokListXRT: Out of Resources" In the beginning, I thought it's caused by the growing size of vendor-dbx. However, we found the following messages after set SHIM_VERBOSE: max_var_sz:8000 remaining_sz:85EC max_storage_sz:9000 SetVariable(“MokListXRT”, ... varsz=0x1404) = Out of Resources Even though the firmware claimed the remaining storage size is 0x85EC and the maximum variable size is 0x8000, it still rejected MokListXRT with size 0x1404. It seems that the return values from QueryVariableInfo() are not reliable. Since this firmware didn't really support Secure Boot, the variable mirroring is not so critical, so we can just accept the failure of import_mok_state() and continue boot. (*) https://bugzilla.suse.com/show_bug.cgi?id=1185261 Signed-off-by: Gary Lin <glin@suse.com>
2021-03-30Fix an off-by-one on the sbat self-check.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2021-03-30sbat: add more dprint()Peter Jones
This adds dprint() to a bunch of our error returns. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-03-27Change SBAT variable name to SbatLevelJan Setje-Eilers
Because a few shim builds were signed that did not properly initialize the SBAT variable, and in doing so deleted valid SBAT variables, we need to use a different name. This changes the name from "SBAT" to "SbatLevel". Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
2021-03-18shim: Use the default loader if an EFI_LOAD_OPTION can't be parsedJavier Martinez Canillas
If the LoadOptions string count is zero, then it's assumed that it is an EFI_LOAD_OPTION and the OptionalData field attempt to be parsed. If that fails as well, in the second stage was set to the default loader path. But this behaviour was changed by the commit 018b74d2 ("shim: attempt to improve the argument handling"), and not in that case the LoadOptions is attempted to be used as a single string. This breaks some firmwares that return something in the LoadOptions but are not a proper EFI device path. Instead of making assumptions about the LoadOptions if can't be parsed correctly, just use the default loader as it was done before that commit. This fixes booting on a Gigabyte GA-Z97X-SLI mainboard that contains the following bytes as LoadOptions: 0x41 0x4d 0x42 0x4f ('AMBO'). Reported-by: Thomas Frauendorfer | Miray Software <tf@miray.de> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2021-03-15shim: Fix a NULL pointer dereference caused by start not being setJavier Martinez Canillas
Commit 018b74d2d69 ("shim: attempt to improve the argument handling") added added workarounds for a couple of LoadOption problems on some systems, but introduced a regression since the is_our_path() function can be called with a NULL start UCS-2 string. If there's only one string, set start to the start of LoadOptions. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2021-03-12Fix a plausible NULL dereference.Peter Jones
scan-build kindly pointed out: | shim.c:1568:10: warning: Array access (from variable 'start') results in a null pointer dereference [core.NullDereference] | while (start[loader_len++] != L'\0'); | ^~~~~~~~~~~~~~~~~~~ | 1 warning generated. It thinks that because of a bad assumption it's making because of the test immediately before it, which isn't currently necessary /at all/. In fact, neither is this loop; it appears to be vestigial and the goal was done in the loop above it. This patch just solves for how much space is left arithmetically instead. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-03-12Make ENABLE_SHIM_DEVEL work better.Peter Jones
This fixes ENABLE_SHIM_DEVEL to actually work, and also makes our "goto die" failure behavior change (to wait considerably longer) based on it. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-03-11shim: simplify sbat self-check logic.Peter Jones
There's no reason to do the work to set an initial SBAT variable twice, or to do it /after/ the self check. This changes it to do it once, before the self check, and then only raise an error if we're in secure mode. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-03-11If the SBAT UEFI variable is not set, initialize it as a bootservices variable.Jan Setje-Eilers
2021-03-10shim: attempt to improve the argument handlingPaul Moore
"So, load options are a giant pain in the ass." - Peter Jones This patch attempts to workaround two LoadOption problems seen on my test system: arguments separated with only whitespace (L" ") and strings that aren't properly NULL terminated. In addition to my test system, it appears at least one other person has run into a similar problem and I can reproduce the whitespace delimiter issue with QEMU+OVMF (OEMU v5.2.0, OVMF v202011). * https://github.com/rhboot/shim/issues/181 For reference, using QEMU+OVMF and a simple test application, "test.efi", which does a hexdump of LoadOptions I see the following when run via the UEFI shell: FS0:\> test.efi one two three LoadOptions: 0000: 74 00 65 00 73 00 74 00 2E 00 65 00 66 00 69 00 t.e.s.t...e.f.i. 0016: 20 00 6F 00 6E 00 65 00 20 00 74 00 77 00 6F 00 ..o.n.e...t.w.o. 0032: 20 00 74 00 68 00 72 00 65 00 65 00 00 00 ..t.h.r.e.e... Signed-off-by: Paul Moore <pmoore2@cisco.com>
2021-03-10Fix compilation for older gccAlex Burmashev
Signed-off-by: Alex Burmashev <alexander.burmashev@oracle.com>