Module Name:    src
Committed By:   ryo
Date:           Sun May 29 16:39:22 UTC 2022

Modified Files:
        src/sys/arch/aarch64/aarch64: db_interface.c

Log Message:
Use the PAR register to check for accessibility in db_(read|write)_bytes().

db_(read|write)_bytes() uses the TTBR[01] at that time, so it must check
if it is accessible in context at that time, not pmap_extract()
which uses the struct pmap of the process.

- It also checks if the address is writable.
- db_write_bytes() also requires ARMV81_PAN control.


To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/aarch64/aarch64/db_interface.c

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/db_interface.c
diff -u src/sys/arch/aarch64/aarch64/db_interface.c:1.17 src/sys/arch/aarch64/aarch64/db_interface.c:1.18
--- src/sys/arch/aarch64/aarch64/db_interface.c:1.17	Thu May 26 17:11:05 2022
+++ src/sys/arch/aarch64/aarch64/db_interface.c	Sun May 29 16:39:22 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.17 2022/05/26 17:11:05 ryo Exp $ */
+/* $NetBSD: db_interface.c,v 1.18 2022/05/29 16:39:22 ryo Exp $ */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.17 2022/05/26 17:11:05 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.18 2022/05/29 16:39:22 ryo Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -39,7 +39,9 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface
 #include <uvm/pmap/pmap_pvt.h>
 #endif
 
+#include <aarch64/armreg.h>
 #include <aarch64/db_machdep.h>
+#include <aarch64/locore.h>
 #include <aarch64/machdep.h>
 #include <aarch64/pmap.h>
 
@@ -57,19 +59,40 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface
 
 db_regs_t ddb_regs;
 
-static int
-db_validate_address(vaddr_t addr)
+static bool
+db_accessible_address(vaddr_t addr, bool readonly)
 {
-	struct proc *p = curcpu()->ci_onproc->l_proc;
-	struct pmap *pmap;
+	register_t s;
+	uint64_t par;
+	int space;
 
-	if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap ||
-	    addr >= VM_MAXUSER_ADDRESS)
-		pmap = pmap_kernel();
-	else
-		pmap = p->p_vmspace->vm_map.pmap;
+	space = aarch64_addressspace(addr);
+	if (space != AARCH64_ADDRSPACE_LOWER &&
+	    space != AARCH64_ADDRSPACE_UPPER)
+		return false;
+
+	s = daif_disable(DAIF_I|DAIF_F);
 
-	return (pmap_extract(pmap, addr, NULL) == false);
+	switch (aarch64_addressspace(addr)) {
+	case AARCH64_ADDRSPACE_LOWER:
+		if (readonly)
+			reg_s1e0r_write(addr);
+		else
+			reg_s1e0w_write(addr);
+		break;
+	case AARCH64_ADDRSPACE_UPPER:
+		if (readonly)
+			reg_s1e1r_write(addr);
+		else
+			reg_s1e1w_write(addr);
+		break;
+	}
+	isb();
+	par = reg_par_el1_read();
+
+	reg_daif_write(s);
+
+	return ((par & PAR_F) == 0);
 }
 
 void
@@ -82,7 +105,7 @@ db_read_bytes(vaddr_t addr, size_t size,
 		const vaddr_t va = (vaddr_t)src;
 		uintptr_t tmp;
 
-		if (lastpage != atop(va) && db_validate_address(va)) {
+		if (lastpage != atop(va) && !db_accessible_address(va, true)) {
 			db_printf("address %p is invalid\n", src);
 			memset(data, 0, size);	/* stubs are filled by zero */
 			return;
@@ -190,17 +213,19 @@ db_write_bytes(vaddr_t addr, size_t size
 		data += s;
 	}
 
-	/* XXX: need to check read only block/page */
 	for (dst = (char *)addr; size > 0;) {
 		const vaddr_t va = (vaddr_t)dst;
 		uintptr_t tmp;
 
-		if (lastpage != atop(va) && db_validate_address(va)) {
+		if (lastpage != atop(va) && !db_accessible_address(va, false)) {
 			db_printf("address %p is invalid\n", dst);
 			return;
 		}
 		lastpage = atop(va);
 
+		if (aarch64_pan_enabled)
+			reg_pan_write(0); /* disable PAN */
+
 		tmp = (uintptr_t)dst | (uintptr_t)data;
 		if (size >= 8 && (tmp & 7) == 0) {
 			*(uint64_t *)dst = *(const uint64_t *)data;
@@ -221,6 +246,9 @@ db_write_bytes(vaddr_t addr, size_t size
 			*dst++ = *data++;
 			size--;
 		}
+
+		if (aarch64_pan_enabled)
+			reg_pan_write(1); /* enable PAN */
 	}
 }
 

Reply via email to