Revise implementation of pmap_protect(9) in preparation for execute-only
authorkettenis <kettenis@openbsd.org>
Thu, 19 Jan 2023 20:17:11 +0000 (20:17 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 19 Jan 2023 20:17:11 +0000 (20:17 +0000)
support.  The current implementation doesn't handle the transition from
RWX to RW correctly.  Also generalize the pmap_write_protect() function
in recognition of the fact that execute permission, write permission,
and in the future read permission on executable pages, are handled by
separate bits.

ok deraadt@, mpi@

sys/arch/amd64/amd64/pmap.c
sys/arch/amd64/include/pmap.h

index 893f840..ea9b2c1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.156 2022/11/29 21:41:39 guenther Exp $     */
+/*     $OpenBSD: pmap.c,v 1.157 2023/01/19 20:17:11 kettenis Exp $     */
 /*     $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
 
 /*
@@ -2105,7 +2105,8 @@ pmap_clear_attrs(struct vm_page *pg, unsigned long clearbits)
 void
 pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
 {
-       pt_entry_t nx, *spte, *epte;
+       pt_entry_t *spte, *epte;
+       pt_entry_t clear = 0, set = 0;
        vaddr_t blockend;
        int shootall = 0, shootself;
        vaddr_t va;
@@ -2118,9 +2119,10 @@ pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
        sva &= PG_FRAME;
        eva &= PG_FRAME;
 
-       nx = 0;
+       if (!(prot & PROT_WRITE))
+               clear = PG_RW;
        if (!(prot & PROT_EXEC))
-               nx = pg_nx;
+               set |= pg_nx;
 
        if ((eva - sva > 32 * PAGE_SIZE) && sva < VM_MIN_KERNEL_ADDRESS)
                shootall = 1;
@@ -2158,8 +2160,8 @@ pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
                for (/*null */; spte < epte ; spte++) {
                        if (!pmap_valid_entry(*spte))
                                continue;
-                       pmap_pte_clearbits(spte, PG_RW);
-                       pmap_pte_setbits(spte, nx);
+                       pmap_pte_clearbits(spte, clear);
+                       pmap_pte_setbits(spte, set);
                }
        }
 
index 4cfd83e..3660f44 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.h,v 1.83 2023/01/17 19:29:09 kettenis Exp $      */
+/*     $OpenBSD: pmap.h,v 1.84 2023/01/19 20:17:12 kettenis Exp $      */
 /*     $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $    */
 
 /*
@@ -475,12 +475,10 @@ pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
 static inline void
 pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
 {
-       if ((prot & PROT_WRITE) == 0) {
-               if (prot & (PROT_READ| PROT_EXEC)) {
-                       pmap_write_protect(pmap, sva, eva, prot);
-               } else {
-                       pmap_remove(pmap, sva, eva);
-               }
+       if (prot != PROT_NONE) {
+               pmap_write_protect(pmap, sva, eva, prot);
+       } else {
+               pmap_remove(pmap, sva, eva);
        }
 }