Author: andrew
Date: Wed Oct 30 17:32:35 2019
New Revision: 354193
URL: https://svnweb.freebsd.org/changeset/base/354193

Log:
  Set the userspace execute never bit on kernel mappings.
  
  Arm64 allows us to create execute only mappings. To make sure userspace is
  unable to accidentally execute kernel code set the user execute never
  bit in the kernel page tables.
  
  MFC after:    1 week
  Sponsored by: DARPA, AFRL

Modified:
  head/sys/arm64/arm64/locore.S
  head/sys/arm64/arm64/pmap.c

Modified: head/sys/arm64/arm64/locore.S
==============================================================================
--- head/sys/arm64/arm64/locore.S       Wed Oct 30 17:18:11 2019        
(r354192)
+++ head/sys/arm64/arm64/locore.S       Wed Oct 30 17:32:35 2019        
(r354193)
@@ -556,6 +556,7 @@ build_l2_block_pagetable:
        lsl     x12, x7, #2
        orr     x12, x12, #L2_BLOCK
        orr     x12, x12, #(ATTR_AF)
+       orr     x12, x12, #(ATTR_UXN)
 #ifdef SMP
        orr     x12, x12, ATTR_SH(ATTR_SH_IS)
 #endif

Modified: head/sys/arm64/arm64/pmap.c
==============================================================================
--- head/sys/arm64/arm64/pmap.c Wed Oct 30 17:18:11 2019        (r354192)
+++ head/sys/arm64/arm64/pmap.c Wed Oct 30 17:32:35 2019        (r354193)
@@ -761,7 +761,7 @@ pmap_bootstrap_l3(vm_offset_t l1pt, vm_offset_t va, vm
 
                pa = pmap_early_vtophys(l1pt, l3pt);
                pmap_store(&l2[l2_slot],
-                   (pa & ~Ln_TABLE_MASK) | L2_TABLE);
+                   (pa & ~Ln_TABLE_MASK) | ATTR_UXN | L2_TABLE);
                l3pt += PAGE_SIZE;
        }
 
@@ -1174,6 +1174,8 @@ pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_
        attr = ATTR_DEFAULT | ATTR_IDX(mode) | L3_PAGE;
        if (mode == DEVICE_MEMORY)
                attr |= ATTR_XN;
+       else
+               attr |= ATTR_UXN;
 
        va = sva;
        while (size != 0) {
@@ -1289,7 +1291,7 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
 
                m = ma[i];
                pa = VM_PAGE_TO_PHYS(m) | ATTR_DEFAULT | ATTR_AP(ATTR_AP_RW) |
-                   ATTR_IDX(m->md.pv_memattr) | L3_PAGE;
+                   ATTR_UXN | ATTR_IDX(m->md.pv_memattr) | L3_PAGE;
                if (m->md.pv_memattr == DEVICE_MEMORY)
                        pa |= ATTR_XN;
                pte = pmap_l2_to_l3(pde, va);
@@ -3194,6 +3196,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
                new_l3 |= ATTR_SW_WIRED;
        if (va < VM_MAXUSER_ADDRESS)
                new_l3 |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN;
+       else
+               new_l3 |= ATTR_UXN;
        if ((m->oflags & VPO_UNMANAGED) == 0) {
                new_l3 |= ATTR_SW_MANAGED;
                if ((prot & VM_PROT_WRITE) != 0) {
@@ -3456,6 +3460,8 @@ pmap_enter_2mpage(pmap_t pmap, vm_offset_t va, vm_page
                new_l2 |= ATTR_XN;
        if (va < VM_MAXUSER_ADDRESS)
                new_l2 |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN;
+       else
+               new_l2 |= ATTR_UXN;
        return (pmap_enter_l2(pmap, va, new_l2, PMAP_ENTER_NOSLEEP |
            PMAP_ENTER_NOREPLACE | PMAP_ENTER_NORECLAIM, NULL, lockp) ==
            KERN_SUCCESS);
@@ -3754,6 +3760,8 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, v
                l3_val |= ATTR_XN;
        if (va < VM_MAXUSER_ADDRESS)
                l3_val |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN;
+       else
+               l3_val |= ATTR_UXN;
 
        /*
         * Now validate mapping with RO protection
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to