[metal] Allow more fine-grained control over page permissions (#663)

- use PAGE_RSRV bit (originally only for blinkenlights),
  rather than PAGE_V bit, to indicate that a virtual address
  page has been reserved — this should allow a program to
  create & reserve inaccessible "guard pages"
- mark page table entries for non-code pages with PAGE_XD bit,
  which should be supported on (circa) post-2004 x86-64 CPUs
This commit is contained in:
tkchia 2022-10-13 02:07:11 +08:00 committed by GitHub
parent 0f89140882
commit d38700687a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 14 deletions

View file

@ -43,7 +43,7 @@ noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot,
addr = 4096;
for (i = 0; i < size; i += 4096) {
pte = __get_virtual(mm, pml4t, addr + i, false);
if (pte && (*pte & PAGE_V)) {
if (pte && (*pte & (PAGE_V | PAGE_RSRV))) {
addr = MAX(addr, sys_mmap_metal_break) + i + 4096;
i = 0;
}
@ -55,7 +55,13 @@ noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot,
pte = __get_virtual(mm, pml4t, addr + i, true);
if (pte && page) {
__clear_page(BANE + page);
*pte = page | ((prot & PROT_WRITE) ? PAGE_RW : 0) | PAGE_U | PAGE_V;
page |= PAGE_RSRV | PAGE_U;
if ((prot & PROT_WRITE))
page |= PAGE_V | PAGE_RW;
else if ((prot & (PROT_READ | PROT_EXEC)))
page |= PAGE_V;
if (!(prot & PROT_EXEC)) page |= PAGE_XD;
*pte = page;
} else {
addr = -1;
break;