summaryrefslogtreecommitdiff
path: root/pe.c
AgeCommit message (Collapse)Author
2025-02-25pe: read_header(): allow skipping SecDir content validationPeter Jones
When we're parsing the PE header of shim itself from the Loaded Image object, the signatures aren't present, but the Certificate Table entry in the Data Directory has not been cleared, so it'll fail verification. We know when we're doing that, so this patch makes that test optional. Signed-off-by: Peter Jones <pjones@redhat.com>
2025-02-24Move memory attribute support to its own file.Peter Jones
This moves the EFI Memory Attribute Protocol helper functions to their own file, since they're not related to PE things. Signed-off-by: Peter Jones <pjones@redhat.com>
2025-02-24get_mem_attrs(): ensure an error code is set on failurePeter Jones
This changes get_mem_attrs() to return EFI_UNSUPPORTED if LibLocateProtocol() does not return an error but does give us a NULL pointer. Signed-off-by: Peter Jones <pjones@redhat.com>
2025-02-11Don't print full screen error dialog from handle_image() when called in_protocolMate Kukri
This isn't desirable when GRUB has control of the screen, and would mess its content up. Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
2025-02-04pe: Enhance debug report for update_mem_attrsJianyong Wu
When memory attributes cannot be updated due to misalignment with 4K or when the size is 0, the debug printout lacks sufficient clarity to indicate the issue. To enhance troubleshooting, it is crucial to generate an error log that explicitly states the failure to execute the expected action. This error log will be visible even when the debug level log is not enabled, thereby significantly reducing debugging time. Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2023-12-05Print errors when setting/clearing memory attrsPeter Jones
When working on issues with the memory attributes API, shim does not currently display any errors which are returned from the API itself. This adds those error messages. Resolves #575 Signed-off-by: Peter Jones <pjones@redhat.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-07-19Correctly free memory allocated in handle_image()Dennis Tseng
Currently pe's handle_image() function has two related issues, which are a memory leak in most error paths and an incorrect FreePool() call in some error paths. This patch adds the correct FreePages() calls to most error paths, and switches the FreePool() call to match them. [commit message re-written to be more informative by pjones] Signed-off-by: Dennis Tseng <dennis.tseng@suse.com>
2023-06-23Split pe.c up even more.Peter Jones
This moves the parts of pe.c that *don't* depend on Cryptlib into pe-relocate.c, so we can write test cases for them without having to make a second openssl build without EFI support. Signed-off-by: Peter Jones <pjones@redhat.com>
2023-06-21pe: only process RelocDir->Size of reloc sectionMike Beaton
Previously processing full padding-aligned Section->Misc.VirtualSize relied on padding reloc entries being inserted by GenFw, which is not required by spec. This changes it to only process the amount referenced by Size, rather than VirtualSize which may be bigger than the data present. Signed-off-by: Mike Beaton <mjsbeaton@gmail.com>
2023-01-27pe: Add IS_PAGE_ALIGNED macroNicholas Bishop
This makes some checks in `get_mem_attrs` and `update_mem_attrs` clearer. Also add `test-pe-util.c` with a test for the new macro. The file is named that way instead of `test-pe.c` to avoid having to get `pe.c` building in the unit test environment. Signed-off-by: Nicholas Bishop <nicholasbishop@google.com>
2023-01-27pe: Align section size up to page size for mem attrsNicholas Bishop
Setting memory attributes is generally done at page granularity, and this is enforced by checks in `get_mem_attrs` and `update_mem_attrs`. But unlike the section address, the section size isn't necessarily aligned to 4KiB. Round up the section size to fix this. Signed-off-by: Nicholas Bishop <nicholasbishop@google.com>
2022-11-14pe: Fix image section entry-point validationIlya Okomin
Seen mokmanager image load failure '2 sections contain entry point' for shim built on Oracle Linux 9 aarch64. found_entry_point counter in handle_image() uses SizeOfRawData to calculate section boundary. PE spec defines VirtualSize for the total size of the section when loaded into memory. SizeOfRawData is the size of the section (for object files) or the size of the initialized data on disk. Fix this issue by updating section in-memory size limit to VirtualSize. Resolves: #517 Signed-off-by: Ilya Okomin <ilya.okomin@oracle.com>
2022-10-04shim: Flush the memory region from i-cache before executiondann frazier
We've seen crashes in early GRUB code on an ARM Cortex-A72-based platform that point at seemingly harmless instructions. Flushing the i-cache of those instructions prior to executing has been shown to avoid the problem, which has parallels with this story: https://www.mail-archive.com/osv-dev@googlegroups.com/msg06203.html Add a cache flushing utility function and provide an implementation using a GCC intrinsic. This will need to be extended to support other compilers. Note that this intrinsic is a no-op for x86 platforms. This fixes issue #498. Signed-off-by: dann frazier <dann.frazier@canonical.com>
2022-05-24Also avoid CVE-2022-28737 in verify_image()Peter Jones
PR 446 ("Add verify_image") duplicates some of the code affected by Chris Coulson's defense in depth patch against CVE-2022-28737 ("pe: Perform image verification earlier when loading grub"). This patch makes the same change to the new function. Signed-off-by: Peter Jones <pjones@redhat.com>
2022-05-24pe: Perform image verification earlier when loading grubChris Coulson
The second stage loader was being verified after loading it into memory. As an additional hardening measure to avoid performing risky memcpys using header fields from a potentially specially crafted image, perform the verification before this so that it can be rejected earlier. Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
2022-05-24pe: Fix a buffer overflow when SizeOfRawData > VirtualSizeChris Coulson
During image loading, the size of the destination buffer for the image is determined by the SizeOfImage field in the optional header. The start and end virtual addresses of each section, as determined by each section's VirtualAddress and VirtualSize fields, are bounds checked against the allocated buffer. However, the amount of data copied to the destination buffer is determined by the section's SizeOfRawData filed. If this is larger than the VirtualSize, then the copy can overflow the destination buffer. Fix this by limiting the amount of data to copy to the section's VirtualSize. In the case where a section has SizeOfRawData > VirtualSize, the excess data is discarded. This fixes CVE-2022-28737 Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
2022-05-17Add MokPolicy variable and MOK_POLICY_REQUIRE_NXPeter Jones
This adds a new MoK variable, MokPolicy (&MokPolicyRT) that's intended as a bitmask of machine owner policy choices, and the bit MOK_POLICY_REQUIRE_NX. This bit specifies whether it is permissible to load binaries which do not support NX mitigations, and it currently defaults to allowing such binaries to be loaded. The broader intention here is to migrate all of the MoK policy variables that are really just on/off flags to this variable. Signed-off-by: Peter Jones <pjones@redhat.com>
2022-05-17PE Loader: support and require NXPeter Jones
This adds support in our PE loader for NX support utilizing the EFI_MEMORY_ATTRIBUTE protocol. Specifically, it changes the loader such that: - binaries without the EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT flag set in the Optional Header are rejected as EFI_UNSUPPORTED - binaries with non-discardable sections that have both the EFI_SCN_MEM_WRITE and EFI_SCN_MEM_EXECUTE flags set are rejected as EFI_UNSUPPORTED - if the EFI_MEMORY_ATTRIBUTE protocol is installed, then: - sections without the EFI_SCN_MEM_READ flag set will be marked with EFI_MEMORY_RP - sections without the EFI_SCN_MEM_WRITE flag set will be marked with EFI_MEMORY_RO - sections without the EFI_SCN_MEM_EXECUTE flag set will be marked with EFI_MEMORY_XP Signed-off-by: Peter Jones <pjones@redhat.com>
2022-05-17Add verify_imageEric Snowberg
In the future we will want to examine binaries without wanting to execute them. Create verify_image based off existing handle_image code. Signed-off-by: Eric Snowberg <eric.snowberg@oracle.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>
2022-02-03pe: missing perror argumentHeinrich Schuchardt
perror(L"%d sections contain entry point\n") lacks an argument corresponding to %d. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2021-09-10pe: simplify generate_hash()Heinrich Schuchardt
Copying the value of datasize_in to two further variables and then using all three randomly in the code makes it hard to read. datasize_in is never changed in generate_hash() so we can do with this parameter alone. Rename it to datasize. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.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-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-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-10Restructure our includes.Peter Jones
This re-structures our includes so we can be sure everything is always including all the system headers in a uniform, predictable way. Temporarily it also adds a bunch of junk at all the places we use variadic functions to specifically pick either the MS (cdecl) or ELF ABIs. I'm not 100% sure that's all correct (see later patch) but it's enough to allow this to build. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-25sbat: Don't assume VirtualSize == SizeOfRawDataChris Coulson
The current code rejects the .sbat section if the VirtualSize and SizeOfRawData fields of the section header aren't the same, but this is too strict. The VirtualSize corresponds to the size of the SBAT metadata and isn't necessarily a multiple of the file alignment. The on-disk size (SizeOfRawData) is a multiple of the file alignment and is zero padded. Make sure that the on-disk size is at least as large as virtual size, and ignore the .sbat section if it isn't. This should fix https://github.com/rhboot/shim/issues/281. Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
2021-02-25sbat: fix the residual "resource section" for SBATGary Lin
Signed-off-by: Gary Lin <glin@suse.com>
2021-02-25SBAT: make our sbat section parser use the csv parserPeter Jones
This makes the .sbat section parser use parse_csv_data(). It also re-names a couple of the structs, because they were still too easy to get lost in. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-25Fix all the places we need UNUSED on arguments.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-19sbat: make shim to parse it's own .sbat section on initJavier Martinez Canillas
This is needed for shim to verify itself when booting, to make sure that shim binaries can't be executed anymore after been revoked by SBAT. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2021-02-19pe.c: move sbat verification to its own function.Peter Jones
handle_image() is quite huge and complex. This patch moves the SBAT validation code from handle_image() to a new function, handle_sbat(). Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-19Don't re-parse the SBAT EFI variable for each binary we load.Javier Martinez Canillas
On a typical boot we validate at least two binaries; parsing the SBAT EFI variable each time, when it should not be changing, is not worth the effort. This patch moves the parsing out to some setup code, instead of doing it during the verification stage. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-19pe.c: parse SBAT variable and perform basic verificationAlex Burmashev
Per Peter Jones suggestion, we will be flexible in what data we expect while parsing the variable. Three fields are mandatory: component_generation, component_name_size, component_name However we also support adding comments and additional information to be added after component name, with ',' as a separator. Those information will be ignored and not used for verification purposes. So: grub,1 and grub,1,wow,this,is,my,comment will provide exactly same set of data for verification. [0]: https://github.com/rhboot/shim/blob/main/SBAT.md Signed-off-by: Alex Burmashev <alexander.burmashev@oracle.com> Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-19sbat: drop the struct sbat and just use two variables insteadPeter Jones
The struct sbat isn't doing anything and only has two fields so let's pass pass those two to the functions directly instead of storing it in a struct. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-16sbat: use correct type for parse_sbat_var() return valueJavier Martinez Canillas
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2021-02-16sbat: remove unused buffer parameter in parse_sbat() functionJavier Martinez Canillas
It's a left over from an early implementation that was never cleaned. Reported-by: Christopher Co <christopher.co@microsoft.com> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2021-02-13SBAT: parse a copy of the table that's got a NUL at the endPeter Jones
Right now we allocate the PE file's contents in RW memory, but hopefully that won't always be the case. Our SBAT parsing, however, very much expects to be able to edit it. We also don't actually know that shim's .sbat section is loaded r/w, so we can't necessarily write there. This patch copies the SBAT data to its own buffer, plus one NUL byte at the end, so we can always be sure that will work. Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-13Add a function to parse the SBAT metadata from the .sbat sectionJavier Martinez Canillas
Parse the SBAT [0] Version-Based Revocation Metadata that's contained in a .sbat data section of the loaded PE binary. This information is used along with data in a SBAT variable to determine if a EFI binary has been revoked. [0]: https://github.com/rhboot/shim/blob/sbat/SBAT.md Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2021-02-13Add the beginning of .sbat parsing stuffPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-13Add some more PE helpers we need for SBATPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-13Refactor some PE handling codePeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2021-02-13Move a bunch of PE-related stuff out of shim.cPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>