solo5: hvt: Enforce that guest executable code is not also writable (W^X)

As part of general hardening, we should enforce both in the ELF loader and at the guest-physical to host-virtual translation layer that any executable code in the guest is not also writable (W^X).

Summary of status for hvt back-ends:

  • Linux/KVM: W^X has been in place for some time (basically forever, since early ukvm days) but not actively enforced. Manual testing confirms the current approach still works as expected, both on x86_64 and ARM64.
  • FreeBSD/vmm: Manual testing shows that the current approach does not work.
  • OpenBSD/vmm: Manual testing shows that the current approach does not work.

There are several sub-issues to this:

  1. hvt_elf_load() currently warns if a PT_LOAD PHDR requests both PF_X and PF_W. This should be changed to a fatal error instead.
  2. hvt_elf_load() should enforce that PT_LOAD PHDRs cannot overlap, otherwise an attacker could construct a malicious ELF defeating the logic in the previous point. While overlapping PT_LOAD PHDRs are not explicitly mentioned in the ELF specification, there is no reason to support this behaviour. This check can be further simplified by enforcing that PT_LOAD PHDRs must be sorted by p_vaddr in the ELF file, which is within the specification.
  3. hvt_elf_load() currently applies PF_x flags from a PT_LOAD PHDR by calling mprotect() on the (host-side) guest memory region. This results in the correct behaviour (enforcement) only on Linux/KVM which updates the guest-physical to host-virtual translation (i.e. EPT on x86_64) as expected. A solution will need to be found to get the same behaviour on FreeBSD/vmm and OpenBSD/vmm.
  4. A test case needs to be added, verifying that .text as seen by the guest is not writable.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 24 (22 by maintainers)

Most upvoted comments

@mato looking back into this, your enforce-nox branch (including the test) disappeared from mato/solo5 – would be great to have the test in solo5 master imho (and maybe mark as failing on FreeBSD/OpenBSD atm)