summaryrefslogtreecommitdiff
path: root/memattrs.c
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2024-05-15 16:13:13 -0400
committerPeter Jones <pjones@redhat.com>2025-02-24 15:24:24 -0500
commit848667d0f3a99401d93c93b3af16b55e3fb28cea (patch)
treedea7e69bef8e20ed687b38c99b7f7e06d3f7abbd /memattrs.c
parent589c3f289e05454be23507767439cb9769a2264a (diff)
downloadefi-boot-shim-848667d0f3a99401d93c93b3af16b55e3fb28cea.tar.gz
efi-boot-shim-848667d0f3a99401d93c93b3af16b55e3fb28cea.zip
shim: add HSIStatus feature
hughsie asked me if I can make shim tell userland what kinds of accesses are allowed to the heap, stack, and allocations on the running platform, so that these could be reported up through fwupd's Host Security ID program (see https://fwupd.github.io/libfwupdplugin/hsi.html ). This adds a new config-only (i.e. not a UEFI variable) variable generated during boot, "/sys/firmware/efi/mok-variables/HSIStatus", which tells us those properties as well as if the EFI Memory Attribute Protocol is present. Signed-off-by: Peter Jones <pjones@redhat.com>
Diffstat (limited to 'memattrs.c')
-rw-r--r--memattrs.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/memattrs.c b/memattrs.c
index 99268cd1..988459c3 100644
--- a/memattrs.c
+++ b/memattrs.c
@@ -164,4 +164,76 @@ update_mem_attrs(uintptr_t addr, uint64_t size,
return ret;
}
+void
+get_hsi_mem_info(void)
+{
+ EFI_STATUS efi_status;
+ uintptr_t addr;
+ uint64_t attrs = 0;
+ uint32_t *tmp_alloc;
+
+ addr = ((uintptr_t)&get_hsi_mem_info) & ~EFI_PAGE_MASK;
+
+ efi_status = get_mem_attrs(addr, EFI_PAGE_SIZE, &attrs);
+ if (EFI_ERROR(efi_status)) {
+error:
+ /*
+ * In this case we can't actually tell anything, so assume
+ * and report the worst case scenario.
+ */
+ hsi_status = SHIM_HSI_STATUS_HEAPX |
+ SHIM_HSI_STATUS_STACKX |
+ SHIM_HSI_STATUS_ROW;
+ dprint(L"Setting HSI to 0x%lx due to error: %r\n", hsi_status, efi_status);
+ return;
+ } else {
+ hsi_status = SHIM_HSI_STATUS_HASMAP;
+ dprint(L"Setting HSI to 0x%lx\n", hsi_status);
+ }
+
+ if (!(hsi_status & SHIM_HSI_STATUS_HASMAP)) {
+ dprint(L"No memory protocol, not testing further\n");
+ return;
+ }
+
+ hsi_status = SHIM_HSI_STATUS_HASMAP;
+ if (attrs & MEM_ATTR_W) {
+ dprint(L"get_hsi_mem_info() is on a writable page: 0x%x->0x%x\n",
+ hsi_status, hsi_status | SHIM_HSI_STATUS_ROW);
+ hsi_status |= SHIM_HSI_STATUS_ROW;
+ }
+
+ addr = ((uintptr_t)&addr) & ~EFI_PAGE_MASK;
+ efi_status = get_mem_attrs(addr, EFI_PAGE_SIZE, &attrs);
+ if (EFI_ERROR(efi_status)) {
+ dprint(L"get_mem_attrs(0x%016llx, 0x%x, &attrs) failed.\n", addr, EFI_PAGE_SIZE);
+ goto error;
+ }
+
+ if (attrs & MEM_ATTR_X) {
+ dprint(L"Stack variable is on an executable page: 0x%x->0x%x\n",
+ hsi_status, hsi_status | SHIM_HSI_STATUS_STACKX);
+ hsi_status |= SHIM_HSI_STATUS_STACKX;
+ }
+
+ tmp_alloc = AllocatePool(EFI_PAGE_SIZE);
+ if (!tmp_alloc) {
+ dprint(L"Failed to allocate heap variable.\n");
+ goto error;
+ }
+
+ addr = ((uintptr_t)tmp_alloc) & ~EFI_PAGE_MASK;
+ efi_status = get_mem_attrs(addr, EFI_PAGE_SIZE, &attrs);
+ FreePool(tmp_alloc);
+ if (EFI_ERROR(efi_status)) {
+ dprint(L"get_mem_attrs(0x%016llx, 0x%x, &attrs) failed.\n", addr, EFI_PAGE_SIZE);
+ goto error;
+ }
+ if (attrs & MEM_ATTR_X) {
+ dprint(L"Heap variable is on an executable page: 0x%x->0x%x\n",
+ hsi_status, hsi_status | SHIM_HSI_STATUS_HEAPX);
+ hsi_status |= SHIM_HSI_STATUS_HEAPX;
+ }
+}
+
// vim:fenc=utf-8:tw=75:noet