Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/aarch64 treat kernel-exec attr and user-exec attr s...



details:   https://anonhg.NetBSD.org/src/rev/df500e79ee89
branches:  trunk
changeset: 363747:df500e79ee89
user:      ryo <ryo%NetBSD.org@localhost>
date:      Fri Aug 10 21:06:42 2018 +0000

description:
treat kernel-exec attr and user-exec attr separately.
kernel cannot execute userland exec page, and user cannot execute kernel page.

diffstat:

 sys/arch/aarch64/aarch64/locore.S |   6 ++--
 sys/arch/aarch64/aarch64/pmap.c   |  52 ++++++++++++++++++++++++---------------
 sys/arch/aarch64/include/pmap.h   |   6 ++--
 3 files changed, 38 insertions(+), 26 deletions(-)

diffs (215 lines):

diff -r 001b8c6e9833 -r df500e79ee89 sys/arch/aarch64/aarch64/locore.S
--- a/sys/arch/aarch64/aarch64/locore.S Fri Aug 10 20:35:52 2018 +0000
+++ b/sys/arch/aarch64/aarch64/locore.S Fri Aug 10 21:06:42 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.17 2018/08/10 17:46:06 maxv Exp $ */
+/*     $NetBSD: locore.S,v 1.18 2018/08/10 21:06:42 ryo Exp $  */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -35,7 +35,7 @@
 #include <aarch64/hypervisor.h>
 #include "assym.h"
 
-RCSID("$NetBSD: locore.S,v 1.17 2018/08/10 17:46:06 maxv Exp $")
+RCSID("$NetBSD: locore.S,v 1.18 2018/08/10 21:06:42 ryo Exp $")
 
 /* #define DEBUG_LOCORE */
 /* #define DEBUG_MMU */
@@ -640,7 +640,7 @@
        adr     x2, start               /* physical addr. before MMU */
        and     x2, x2, #L2_BLK_OA      /* L2 block size aligned (2MB) */
        mov     x1, #VM_MIN_KERNEL_ADDRESS
-       mov     x3, #L2_BLKPAG_ATTR_NORMAL_WB
+       mov     x3, #(L2_BLKPAG_ATTR_NORMAL_WB|LX_BLKPAG_UXN)
 
        /* kernelsize = _end - start */
        ldr     x1, =start
diff -r 001b8c6e9833 -r df500e79ee89 sys/arch/aarch64/aarch64/pmap.c
--- a/sys/arch/aarch64/aarch64/pmap.c   Fri Aug 10 20:35:52 2018 +0000
+++ b/sys/arch/aarch64/aarch64/pmap.c   Fri Aug 10 21:06:42 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.17 2018/08/06 12:50:56 ryo Exp $    */
+/*     $NetBSD: pmap.c,v 1.18 2018/08/10 21:06:42 ryo Exp $    */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.17 2018/08/06 12:50:56 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.18 2018/08/10 21:06:42 ryo Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -163,7 +163,7 @@
 };
 
 static pt_entry_t *_pmap_pte_lookup(struct pmap *, vaddr_t);
-static pt_entry_t _pmap_pte_adjust_prot(pt_entry_t, vm_prot_t, vm_prot_t);
+static pt_entry_t _pmap_pte_adjust_prot(pt_entry_t, vm_prot_t, vm_prot_t, bool);
 static pt_entry_t _pmap_pte_adjust_cacheflags(pt_entry_t, u_int);
 static void _pmap_remove(struct pmap *, vaddr_t, bool);
 static int _pmap_enter(struct pmap *, vaddr_t, paddr_t, vm_prot_t, u_int, bool);
@@ -249,11 +249,15 @@
        oldpte = l2[l2pde_index(va)];
        KDASSERT(!l2pde_valid(oldpte));
 
-       attr = _pmap_pte_adjust_prot(L2_BLOCK, prot, VM_PROT_ALL);
+       attr = _pmap_pte_adjust_prot(L2_BLOCK, prot, VM_PROT_ALL, false);
        attr = _pmap_pte_adjust_cacheflags(attr, flags | PMAP_DEV);
 #ifdef MULTIPROCESSOR
        attr |= LX_BLKPAG_SH_IS;
 #endif
+       /* user cannot execute, and kernel follows the prot */
+       attr |= (LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+       if (prot & VM_PROT_EXECUTE)
+               attr &= ~LX_BLKPAG_PXN;
 
        resid = (size + (L2_SIZE - 1)) & ~(L2_SIZE - 1);
        size = resid;
@@ -780,9 +784,11 @@
 }
 
 static pt_entry_t
-_pmap_pte_adjust_prot(pt_entry_t pte, vm_prot_t prot, vm_prot_t protmask)
+_pmap_pte_adjust_prot(pt_entry_t pte, vm_prot_t prot, vm_prot_t protmask,
+    bool user)
 {
        vm_prot_t masked;
+       pt_entry_t xn;
 
        masked = prot & protmask;
        pte &= ~(LX_BLKPAG_OS_RWMASK|LX_BLKPAG_AF|LX_BLKPAG_AP);
@@ -820,10 +826,12 @@
                break;
        }
 
-       if ((prot & VM_PROT_EXECUTE) == 0)
-               pte |= (LX_BLKPAG_UXN|LX_BLKPAG_PXN);
-       else
-               pte &= ~(LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+       /* executable for kernel or user? first set never exec both */
+       pte |= (LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+       /* and either to executable */
+       xn = user ? LX_BLKPAG_UXN : LX_BLKPAG_PXN;
+       if (prot & VM_PROT_EXECUTE)
+               pte &= ~xn;                     
 
        return pte;
 }
@@ -1052,6 +1060,7 @@
        pt_entry_t *ptep, pte;
        vm_prot_t pteprot;
        uint32_t mdattr;
+       const bool user = (pv->pv_pmap != pmap_kernel());
 
        UVMHIST_FUNC(__func__);
        UVMHIST_CALLED(pmaphist);
@@ -1073,11 +1082,11 @@
                pteprot |= VM_PROT_READ;
        if ((pte & LX_BLKPAG_AP) == LX_BLKPAG_AP_RW)
                pteprot |= VM_PROT_WRITE;
-       if ((pte & (LX_BLKPAG_UXN|LX_BLKPAG_PXN)) == 0)
+       if (l3pte_executable(pte, user))
                pteprot |= VM_PROT_EXECUTE;
 
        /* new prot = prot & pteprot & mdattr */
-       pte = _pmap_pte_adjust_prot(pte, prot & pteprot, mdattr);
+       pte = _pmap_pte_adjust_prot(pte, prot & pteprot, mdattr, user);
        atomic_swap_64(ptep, pte);
 
 #if 0
@@ -1093,6 +1102,7 @@
 pmap_protect(struct pmap *pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
 {
        vaddr_t va;
+       const bool user = (pm != pmap_kernel());
 
        KASSERT((prot & VM_PROT_READ) || !(prot & VM_PROT_WRITE));
 
@@ -1159,8 +1169,8 @@
 #ifdef UVMHIST
                opte = pte;
 #endif
-               executable = l3pte_executable(pte);
-               pte = _pmap_pte_adjust_prot(pte, prot, mdattr);
+               executable = l3pte_executable(pte, user);
+               pte = _pmap_pte_adjust_prot(pte, prot, mdattr, user);
 
                if (!executable && (prot & VM_PROT_EXECUTE)) {
                        /* non-exec -> exec */
@@ -1419,7 +1429,7 @@
 #ifdef UVMHIST
        opte = pte;
 #endif
-       executable = l3pte_executable(pte);
+       executable = l3pte_executable(pte, user);
 
        if (l3pte_valid(pte)) {
                KASSERT(!kenter);       /* pmap_kenter_pa() cannot override */
@@ -1486,7 +1496,7 @@
        }
 #endif
 
-       attr = _pmap_pte_adjust_prot(L3_PAGE, prot, mdattr);
+       attr = _pmap_pte_adjust_prot(L3_PAGE, prot, mdattr, user);
        attr = _pmap_pte_adjust_cacheflags(attr, flags);
        if (VM_MAXUSER_ADDRESS > va)
                attr |= LX_BLKPAG_APUSER;
@@ -1780,7 +1790,7 @@
                pmap_prot = (VM_PROT_READ|VM_PROT_WRITE);
                break;
        }
-       if ((pte & (LX_BLKPAG_UXN|LX_BLKPAG_PXN)) == 0)
+       if (l3pte_executable(pte, pm != pmap_kernel()))
                pmap_prot |= VM_PROT_EXECUTE;
 
        UVMHIST_LOG(pmaphist, "va=%016lx, pmapprot=%08x, accessprot=%08x",
@@ -2063,10 +2073,10 @@
        }
 
        if ((prot & VM_PROT_EXECUTE) == 0) {
-               pte |= (LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+               pte |= LX_BLKPAG_PXN;
        } else {
                pte |= LX_BLKPAG_AF;
-               pte &= ~(LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+               pte &= ~LX_BLKPAG_PXN;
        }
 
        *ptep = pte;
@@ -2152,8 +2162,10 @@
                        pr(", pmap_read");
                if (pte & LX_BLKPAG_OS_WRITE)
                        pr(", pmap_write");
-               if ((pte & (LX_BLKPAG_UXN|LX_BLKPAG_PXN)) == 0)
-                       pr(", executable");
+               if ((pte & LX_BLKPAG_UXN) == 0)
+                       pr(", user-executable");
+               if ((pte & LX_BLKPAG_PXN) == 0)
+                       pr(", kernel-executable");
 
        } else {
                /* L1 and L2 pde */
diff -r 001b8c6e9833 -r df500e79ee89 sys/arch/aarch64/include/pmap.h
--- a/sys/arch/aarch64/include/pmap.h   Fri Aug 10 20:35:52 2018 +0000
+++ b/sys/arch/aarch64/include/pmap.h   Fri Aug 10 21:06:42 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.7 2018/08/06 12:50:56 ryo Exp $ */
+/* $NetBSD: pmap.h,v 1.8 2018/08/10 21:06:42 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -95,8 +95,8 @@
 #define l2pde_is_table(pde)    (((pde) & LX_TYPE) == LX_TYPE_TBL)
 
 #define l3pte_pa(pde)          ((paddr_t)((pde) & LX_TBL_PA))
-#define l3pte_executable(pde)  \
-    (((pde) & (LX_BLKPAG_UXN|LX_BLKPAG_PXN)) != (LX_BLKPAG_UXN|LX_BLKPAG_PXN))
+#define l3pte_executable(pde,user)     \
+    (((pde) & ((user) ? LX_BLKPAG_UXN : LX_BLKPAG_PXN)) == 0)
 #define l3pte_readable(pde)    ((pde) & LX_BLKPAG_AF)
 #define l3pte_writable(pde)    \
     (((pde) & (LX_BLKPAG_AF|LX_BLKPAG_AP)) == (LX_BLKPAG_AF|LX_BLKPAG_AP_RW))



Home | Main Index | Thread Index | Old Index