Module Name:    src
Committed By:   ryo
Date:           Fri Aug 10 21:06:42 UTC 2018

Modified Files:
        src/sys/arch/aarch64/aarch64: locore.S pmap.c
        src/sys/arch/aarch64/include: pmap.h

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


To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/aarch64/aarch64/locore.S \
    src/sys/arch/aarch64/aarch64/pmap.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/aarch64/include/pmap.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/aarch64/aarch64/locore.S
diff -u src/sys/arch/aarch64/aarch64/locore.S:1.17 src/sys/arch/aarch64/aarch64/locore.S:1.18
--- src/sys/arch/aarch64/aarch64/locore.S:1.17	Fri Aug 10 17:46:06 2018
+++ src/sys/arch/aarch64/aarch64/locore.S	Fri Aug 10 21:06:42 2018
@@ -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 <r...@nerv.org>
@@ -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 @@ arm_boot_l0pt_init:
 	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
Index: src/sys/arch/aarch64/aarch64/pmap.c
diff -u src/sys/arch/aarch64/aarch64/pmap.c:1.17 src/sys/arch/aarch64/aarch64/pmap.c:1.18
--- src/sys/arch/aarch64/aarch64/pmap.c:1.17	Mon Aug  6 12:50:56 2018
+++ src/sys/arch/aarch64/aarch64/pmap.c	Fri Aug 10 21:06:42 2018
@@ -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 <r...@nerv.org>
@@ -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 @@ struct pv_entry {
 };
 
 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 @@ _pmap_map_chunk(pd_entry_t *l2, vaddr_t 
 	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 @@ _pmap_pte_lookup(struct pmap *pm, vaddr_
 }
 
 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 @@ _pmap_pte_adjust_prot(pt_entry_t pte, vm
 		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 @@ _pmap_protect_pv(struct vm_page *pg, str
 	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 @@ _pmap_protect_pv(struct vm_page *pg, str
 		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 @@ void
 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 @@ pmap_protect(struct pmap *pm, vaddr_t sv
 #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 @@ _pmap_enter(struct pmap *pm, vaddr_t va,
 #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 @@ _pmap_enter(struct pmap *pm, vaddr_t va,
 	}
 #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_fault_fixup(struct pmap *pm, vaddr_
 		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 @@ pmap_kvattr(vaddr_t va, vm_prot_t prot)
 	}
 
 	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 @@ pmap_db_pte_print(pt_entry_t pte, int le
 			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 */

Index: src/sys/arch/aarch64/include/pmap.h
diff -u src/sys/arch/aarch64/include/pmap.h:1.7 src/sys/arch/aarch64/include/pmap.h:1.8
--- src/sys/arch/aarch64/include/pmap.h:1.7	Mon Aug  6 12:50:56 2018
+++ src/sys/arch/aarch64/include/pmap.h	Fri Aug 10 21:06:42 2018
@@ -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 @@ struct vm_page_md {
 #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))

Reply via email to