diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | include/memattrs.h | 15 | ||||
| -rw-r--r-- | memattrs.c | 167 | ||||
| -rw-r--r-- | pe.c | 152 | ||||
| -rw-r--r-- | shim.h | 1 |
5 files changed, 185 insertions, 154 deletions
@@ -38,9 +38,9 @@ CFLAGS += -DENABLE_SHIM_CERT else TARGETS += $(MMNAME) $(FBNAME) endif -OBJS = shim.o globals.o mok.o netboot.o cert.o dp.o loader-proto.o tpm.o version.o errlog.o sbat.o sbat_data.o sbat_var.o pe.o pe-relocate.o httpboot.o csv.o load-options.o utils.o +OBJS = shim.o globals.o memattrs.o mok.o netboot.o cert.o dp.o loader-proto.o tpm.o version.o errlog.o sbat.o sbat_data.o sbat_var.o pe.o pe-relocate.o httpboot.o csv.o load-options.o utils.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer -ORIG_SOURCES = shim.c globals.c mok.c netboot.c dp.c loader-proto.c tpm.c errlog.c sbat.c pe.c pe-relocate.c httpboot.c shim.h version.h $(wildcard include/*.h) cert.S sbat_var.S +ORIG_SOURCES = shim.c globals.c memattrs.c mok.c netboot.c dp.c loader-proto.c tpm.c errlog.c sbat.c pe.c pe-relocate.c httpboot.c shim.h version.h $(wildcard include/*.h) cert.S sbat_var.S MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o errlog.o sbat_data.o globals.o dp.o ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h) FALLBACK_OBJS = fallback.o tpm.o errlog.o sbat_data.o globals.o utils.o diff --git a/include/memattrs.h b/include/memattrs.h new file mode 100644 index 00000000..8fefef22 --- /dev/null +++ b/include/memattrs.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * memattrs.h - EFI and DXE memory attribute helpers + * Copyright Peter Jones <pjones@redhat.com> + */ + +#ifndef SHIM_MEMATTRS_H_ +#define SHIM_MEMATTRS_H_ + +extern EFI_STATUS get_mem_attrs (uintptr_t addr, size_t size, uint64_t *attrs); +extern EFI_STATUS update_mem_attrs(uintptr_t addr, uint64_t size, + uint64_t set_attrs, uint64_t clear_attrs); + +#endif /* !SHIM_MEMATTRS_H_ */ +// vim:fenc=utf-8:tw=75:noet diff --git a/memattrs.c b/memattrs.c new file mode 100644 index 00000000..99268cd1 --- /dev/null +++ b/memattrs.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * memattrs.c - EFI and DXE memory attribute helpers + * Copyright Peter Jones <pjones@redhat.com> + */ + +#include "shim.h" + +static inline uint64_t +shim_mem_attrs_to_uefi_mem_attrs (uint64_t attrs) +{ + uint64_t ret = EFI_MEMORY_RP | + EFI_MEMORY_RO | + EFI_MEMORY_XP; + + if (attrs & MEM_ATTR_R) + ret &= ~EFI_MEMORY_RP; + + if (attrs & MEM_ATTR_W) + ret &= ~EFI_MEMORY_RO; + + if (attrs & MEM_ATTR_X) + ret &= ~EFI_MEMORY_XP; + + return ret; +} + +static inline uint64_t +uefi_mem_attrs_to_shim_mem_attrs (uint64_t attrs) +{ + uint64_t ret = MEM_ATTR_R | + MEM_ATTR_W | + MEM_ATTR_X; + + if (attrs & EFI_MEMORY_RP) + ret &= ~MEM_ATTR_R; + + if (attrs & EFI_MEMORY_RO) + ret &= ~MEM_ATTR_W; + + if (attrs & EFI_MEMORY_XP) + ret &= ~MEM_ATTR_X; + + return ret; +} + +EFI_STATUS +get_mem_attrs (uintptr_t addr, size_t size, uint64_t *attrs) +{ + EFI_MEMORY_ATTRIBUTE_PROTOCOL *proto = NULL; + EFI_PHYSICAL_ADDRESS physaddr = addr; + EFI_STATUS efi_status; + + efi_status = LibLocateProtocol(&EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID, + (VOID **)&proto); + if (EFI_ERROR(efi_status) || !proto) { + dprint(L"No memory attribute protocol found: %r\n", efi_status); + if (!EFI_ERROR(efi_status)) + efi_status = EFI_UNSUPPORTED; + return efi_status; + } + + if (!IS_PAGE_ALIGNED(physaddr) || !IS_PAGE_ALIGNED(size) || size == 0 || attrs == NULL) { + dprint(L"%a called on 0x%llx-0x%llx and attrs 0x%llx\n", + __func__, (unsigned long long)physaddr, + (unsigned long long)(physaddr+size-1), + attrs); + return EFI_SUCCESS; + } + + efi_status = proto->GetMemoryAttributes(proto, physaddr, size, attrs); + if (EFI_ERROR(efi_status)) { + dprint(L"GetMemoryAttributes(..., 0x%llx, 0x%x, 0x%x): %r\n", + physaddr, size, attrs, efi_status); + } else { + *attrs = uefi_mem_attrs_to_shim_mem_attrs (*attrs); + } + + return efi_status; +} + +EFI_STATUS +update_mem_attrs(uintptr_t addr, uint64_t size, + uint64_t set_attrs, uint64_t clear_attrs) +{ + EFI_MEMORY_ATTRIBUTE_PROTOCOL *proto = NULL; + EFI_PHYSICAL_ADDRESS physaddr = addr; + EFI_STATUS efi_status, ret; + uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs; + + efi_status = LibLocateProtocol(&EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID, + (VOID **)&proto); + if (EFI_ERROR(efi_status) || !proto) + return efi_status; + + efi_status = get_mem_attrs (addr, size, &before); + if (EFI_ERROR(efi_status)) + dprint(L"get_mem_attrs(0x%llx, 0x%llx, 0x%llx) -> 0x%lx\n", + (unsigned long long)addr, (unsigned long long)size, + &before, efi_status); + + if (!IS_PAGE_ALIGNED(physaddr) || !IS_PAGE_ALIGNED(size) || size == 0) { + perror(L"Invalid call %a(addr:0x%llx-0x%llx, size:0x%llx, +%a%a%a, -%a%a%a)\n", + __func__, (unsigned long long)physaddr, + (unsigned long long)(physaddr + size - 1), + (unsigned long long)size, + (set_attrs & MEM_ATTR_R) ? "r" : "", + (set_attrs & MEM_ATTR_W) ? "w" : "", + (set_attrs & MEM_ATTR_X) ? "x" : "", + (clear_attrs & MEM_ATTR_R) ? "r" : "", + (clear_attrs & MEM_ATTR_W) ? "w" : "", + (clear_attrs & MEM_ATTR_X) ? "x" : ""); + if (!IS_PAGE_ALIGNED(physaddr)) + perror(L" addr is not page aligned\n"); + if (!IS_PAGE_ALIGNED(size)) + perror(L" size is not page aligned\n"); + if (size == 0) + perror(L" size is 0\n"); + return 0; + } + + uefi_set_attrs = shim_mem_attrs_to_uefi_mem_attrs (set_attrs); + dprint("translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs); + uefi_clear_attrs = shim_mem_attrs_to_uefi_mem_attrs (clear_attrs); + dprint("translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs); + efi_status = EFI_SUCCESS; + if (uefi_set_attrs) { + efi_status = proto->SetMemoryAttributes(proto, physaddr, size, uefi_set_attrs); + if (EFI_ERROR(efi_status)) { + dprint(L"Failed to set memory attrs:0x%0x physaddr:0x%llx size:0x%0lx status:%r\n", + uefi_set_attrs, physaddr, size, efi_status); + } + } + if (!EFI_ERROR(efi_status) && uefi_clear_attrs) { + efi_status = proto->ClearMemoryAttributes(proto, physaddr, size, uefi_clear_attrs); + if (EFI_ERROR(efi_status)) { + dprint(L"Failed to clear memory attrs:0x%0x physaddr:0x%llx size:0x%0lx status:%r\n", + uefi_clear_attrs, physaddr, size, efi_status); + } + } + ret = efi_status; + + efi_status = get_mem_attrs (addr, size, &after); + if (EFI_ERROR(efi_status)) + dprint(L"get_mem_attrs(0x%llx, %llu, 0x%llx) -> 0x%lx\n", + (unsigned long long)addr, (unsigned long long)size, + &after, efi_status); + + dprint(L"set +%a%a%a -%a%a%a on 0x%llx-0x%llx before:%c%c%c after:%c%c%c\n", + (set_attrs & MEM_ATTR_R) ? "r" : "", + (set_attrs & MEM_ATTR_W) ? "w" : "", + (set_attrs & MEM_ATTR_X) ? "x" : "", + (clear_attrs & MEM_ATTR_R) ? "r" : "", + (clear_attrs & MEM_ATTR_W) ? "w" : "", + (clear_attrs & MEM_ATTR_X) ? "x" : "", + (unsigned long long)addr, (unsigned long long)(addr + size - 1), + (before & MEM_ATTR_R) ? 'r' : '-', + (before & MEM_ATTR_W) ? 'w' : '-', + (before & MEM_ATTR_X) ? 'x' : '-', + (after & MEM_ATTR_R) ? 'r' : '-', + (after & MEM_ATTR_W) ? 'w' : '-', + (after & MEM_ATTR_X) ? 'x' : '-'); + + return ret; +} + +// vim:fenc=utf-8:tw=75:noet @@ -395,158 +395,6 @@ err: return efi_status; } -static inline uint64_t -shim_mem_attrs_to_uefi_mem_attrs (uint64_t attrs) -{ - uint64_t ret = EFI_MEMORY_RP | - EFI_MEMORY_RO | - EFI_MEMORY_XP; - - if (attrs & MEM_ATTR_R) - ret &= ~EFI_MEMORY_RP; - - if (attrs & MEM_ATTR_W) - ret &= ~EFI_MEMORY_RO; - - if (attrs & MEM_ATTR_X) - ret &= ~EFI_MEMORY_XP; - - return ret; -} - -static inline uint64_t -uefi_mem_attrs_to_shim_mem_attrs (uint64_t attrs) -{ - uint64_t ret = MEM_ATTR_R | - MEM_ATTR_W | - MEM_ATTR_X; - - if (attrs & EFI_MEMORY_RP) - ret &= ~MEM_ATTR_R; - - if (attrs & EFI_MEMORY_RO) - ret &= ~MEM_ATTR_W; - - if (attrs & EFI_MEMORY_XP) - ret &= ~MEM_ATTR_X; - - return ret; -} - -static EFI_STATUS -get_mem_attrs (uintptr_t addr, size_t size, uint64_t *attrs) -{ - EFI_MEMORY_ATTRIBUTE_PROTOCOL *proto = NULL; - EFI_PHYSICAL_ADDRESS physaddr = addr; - EFI_STATUS efi_status; - - efi_status = LibLocateProtocol(&EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID, - (VOID **)&proto); - if (EFI_ERROR(efi_status) || !proto) { - if (!EFI_ERROR(efi_status)) - efi_status = EFI_UNSUPPORTED; - return efi_status; - } - - if (!IS_PAGE_ALIGNED(physaddr) || !IS_PAGE_ALIGNED(size) || size == 0 || attrs == NULL) { - dprint(L"%a called on 0x%llx-0x%llx and attrs 0x%llx\n", - __func__, (unsigned long long)physaddr, - (unsigned long long)(physaddr+size-1), - attrs); - return EFI_SUCCESS; - } - - efi_status = proto->GetMemoryAttributes(proto, physaddr, size, attrs); - *attrs = uefi_mem_attrs_to_shim_mem_attrs (*attrs); - - return efi_status; -} - -static EFI_STATUS -update_mem_attrs(uintptr_t addr, uint64_t size, - uint64_t set_attrs, uint64_t clear_attrs) -{ - EFI_MEMORY_ATTRIBUTE_PROTOCOL *proto = NULL; - EFI_PHYSICAL_ADDRESS physaddr = addr; - EFI_STATUS efi_status, ret; - uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs; - - efi_status = LibLocateProtocol(&EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID, - (VOID **)&proto); - if (EFI_ERROR(efi_status) || !proto) - return efi_status; - - efi_status = get_mem_attrs (addr, size, &before); - if (EFI_ERROR(efi_status)) - dprint(L"get_mem_attrs(0x%llx, 0x%llx, 0x%llx) -> 0x%lx\n", - (unsigned long long)addr, (unsigned long long)size, - &before, efi_status); - - if (!IS_PAGE_ALIGNED(physaddr) || !IS_PAGE_ALIGNED(size) || size == 0) { - perror(L"Invalid call %a(addr:0x%llx-0x%llx, size:0x%llx, +%a%a%a, -%a%a%a)\n", - __func__, (unsigned long long)physaddr, - (unsigned long long)(physaddr + size - 1), - (unsigned long long)size, - (set_attrs & MEM_ATTR_R) ? "r" : "", - (set_attrs & MEM_ATTR_W) ? "w" : "", - (set_attrs & MEM_ATTR_X) ? "x" : "", - (clear_attrs & MEM_ATTR_R) ? "r" : "", - (clear_attrs & MEM_ATTR_W) ? "w" : "", - (clear_attrs & MEM_ATTR_X) ? "x" : ""); - if (!IS_PAGE_ALIGNED(physaddr)) - perror(L" addr is not page aligned\n"); - if (!IS_PAGE_ALIGNED(size)) - perror(L" size is not page aligned\n"); - if (size == 0) - perror(L" size is 0\n"); - return 0; - } - - uefi_set_attrs = shim_mem_attrs_to_uefi_mem_attrs (set_attrs); - dprint("translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs); - uefi_clear_attrs = shim_mem_attrs_to_uefi_mem_attrs (clear_attrs); - dprint("translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs); - efi_status = EFI_SUCCESS; - if (uefi_set_attrs) { - efi_status = proto->SetMemoryAttributes(proto, physaddr, size, uefi_set_attrs); - if (EFI_ERROR(efi_status)) { - dprint(L"Failed to set memory attrs:0x%0x physaddr:0x%llx size:0x%0lx status:%r\n", - uefi_set_attrs, physaddr, size, efi_status); - } - } - if (!EFI_ERROR(efi_status) && uefi_clear_attrs) { - efi_status = proto->ClearMemoryAttributes(proto, physaddr, size, uefi_clear_attrs); - if (EFI_ERROR(efi_status)) { - dprint(L"Failed to clear memory attrs:0x%0x physaddr:0x%llx size:0x%0lx status:%r\n", - uefi_clear_attrs, physaddr, size, efi_status); - } - } - ret = efi_status; - - efi_status = get_mem_attrs (addr, size, &after); - if (EFI_ERROR(efi_status)) - dprint(L"get_mem_attrs(0x%llx, %llu, 0x%llx) -> 0x%lx\n", - (unsigned long long)addr, (unsigned long long)size, - &after, efi_status); - - dprint(L"set +%a%a%a -%a%a%a on 0x%llx-0x%llx before:%c%c%c after:%c%c%c\n", - (set_attrs & MEM_ATTR_R) ? "r" : "", - (set_attrs & MEM_ATTR_W) ? "w" : "", - (set_attrs & MEM_ATTR_X) ? "x" : "", - (clear_attrs & MEM_ATTR_R) ? "r" : "", - (clear_attrs & MEM_ATTR_W) ? "w" : "", - (clear_attrs & MEM_ATTR_X) ? "x" : "", - (unsigned long long)addr, (unsigned long long)(addr + size - 1), - (before & MEM_ATTR_R) ? 'r' : '-', - (before & MEM_ATTR_W) ? 'w' : '-', - (before & MEM_ATTR_X) ? 'x' : '-', - (after & MEM_ATTR_R) ? 'r' : '-', - (after & MEM_ATTR_W) ? 'w' : '-', - (after & MEM_ATTR_X) ? 'x' : '-'); - - return ret; -} - EFI_STATUS verify_image(void *data, unsigned int datasize, EFI_LOADED_IMAGE *li, PE_COFF_LOADER_IMAGE_CONTEXT *context) @@ -176,6 +176,7 @@ #include "include/ip6config.h" #include "include/load-options.h" #include "include/loader-proto.h" +#include "include/memattrs.h" #include "include/mok.h" #include "include/netboot.h" #include "include/passwordcrypt.h" |
