Everything is crap. That includes UEFI. So apparently some UEFI
firmware thinks it is ok to write to the code segment. And
technically the standard allows this unless the EFI_MEMORY_RO
attribute is set. But of course nobody does.
Anyway, give in. I'll still restrict setting PROT_EXEC a bit even if
it violates the standard. At least until the first firmware shows up
that genuinly tries to execute code in the data segment.
ok?
Index: arch/arm64/dev/efi.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/dev/efi.c,v
retrieving revision 1.3
diff -u -p -r1.3 efi.c
--- arch/arm64/dev/efi.c 12 Jan 2018 14:52:55 -0000 1.3
+++ arch/arm64/dev/efi.c 6 Apr 2018 10:19:41 -0000
@@ -125,7 +125,7 @@ efi_attach(struct device *parent, struct
vaddr_t va = desc->VirtualStart;
paddr_t pa = desc->PhysicalStart;
int npages = desc->NumberOfPages;
- vm_prot_t prot = PROT_READ;
+ vm_prot_t prot = PROT_READ | PROT_WRITE;
#ifdef EFI_DEBUG
printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr
0x%llx\n",
@@ -142,10 +142,20 @@ efi_attach(struct device *parent, struct
if ((desc->Attribute & EFI_MEMORY_WB) == 0)
pa |= PMAP_DEVICE;
+ /*
+ * Only make pages marked as runtime service code
+ * executable. This violates the standard but it
+ * seems we can get away with it.
+ */
if (desc->Type == EfiRuntimeServicesCode)
prot |= PROT_EXEC;
- else
- prot |= PROT_WRITE;
+
+ if (desc->Attribute & EFI_MEMORY_RP)
+ prot &= ~PROT_READ;
+ if (desc->Attribute & EFI_MEMORY_XP)
+ prot &= ~PROT_EXEC;
+ if (desc->Attribute & EFI_MEMORY_RO)
+ prot &= ~PROT_WRITE;
while (npages--) {
pmap_enter(sc->sc_pm, va, pa, prot,