From 82e7d5b2c72994494d7fa7c798611c07e06aa7e1 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 2 Dec 2021 15:51:00 -0500 Subject: [PATCH] post-process-pe: set EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT Currently, system firmware has no means to discover that an EFI Application is compatible with the security feature variously known as NX or w^x. Since at least Revision 8.1, the PE spec supports setting a flag the Optional Header's DllCharacteristics field to inform loaders that an application supports being loaded with NX enabled. In the case of UEFI, there are several things that should be enabled if this flag is set: - EFI_BOOT_SERVICES.AllocatePages() with MemoryType = EfiLoaderCode, EfiBootServicesCode, EfiRuntimeServicesCode, etc, currently must set memory as rwx. This flag set implies that rw- is appropriate, and that the application knows how to use the EFI_MEMORY_ATTRIBUTE protocol to change that to r-x. - EFI_BOOT_SERVICES.AllocatePool() - same as AllocatePages() - EFI_BOOT_SERVICES.LoadImage() - currently must set the stack as rwx. This flag states that it is allowed to be rw- - currently a binary can probably have writable PLTs? This flag allows the loader to not set them writable - I have heard that some firmwares have the 0 page mapped rwx. Obviously this should not be done. Signed-off-by: Peter Jones --- post-process-pe.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/post-process-pe.c b/post-process-pe.c index e32b5249c..275580ada 100644 --- a/post-process-pe.c +++ b/post-process-pe.c @@ -330,6 +330,30 @@ load_pe(const char *const file, void *const data, const size_t datasize, errx(1, "%s: Security directory extends past end", file); } +static void +set_dll_characteristics(PE_COFF_LOADER_IMAGE_CONTEXT *ctx) +{ + uint16_t oldflags, newflags; + + if (image_is_64_bit(ctx->PEHdr)) { + oldflags = ctx->PEHdr->Pe32Plus.OptionalHeader.DllCharacteristics; + } else { + oldflags = ctx->PEHdr->Pe32.OptionalHeader.DllCharacteristics; + } + + newflags = oldflags | EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT; + if (oldflags == newflags) + return; + + debug(INFO, "Updating DLL Characteristics from 0x%04hx to 0x%04hx\n", + oldflags, newflags); + if (image_is_64_bit(ctx->PEHdr)) { + ctx->PEHdr->Pe32Plus.OptionalHeader.DllCharacteristics = newflags; + } else { + ctx->PEHdr->Pe32.OptionalHeader.DllCharacteristics = newflags; + } +} + static void fix_timestamp(PE_COFF_LOADER_IMAGE_CONTEXT *ctx) { @@ -417,6 +441,8 @@ handle_one(char *f) load_pe(f, map, sz, &ctx); + set_dll_characteristics(&ctx); + fix_timestamp(&ctx); fix_checksum(&ctx, map, sz);