Module Name:    src
Committed By:   skrll
Date:           Fri Aug 28 13:36:52 UTC 2020

Modified Files:
        src/sys/arch/arm/arm: armv6_start.S
        src/sys/arch/arm/arm32: arm32_kvminit.c genassym.cf locore.S
        src/sys/arch/arm/include: asan.h
        src/sys/arch/arm/include/arm32: machdep.h

Log Message:
Some KASAN fixes and tweaks

- don't access BSS variables when __md_early
- centralise the INIT_ARM_STACK_{SHIFT,SIZE} defines and create a new
  INIT_ARM_TOTAL_STACK
- Only create L1PT entries in kasan_md_shadow_map_page if
  arm32_kernel_vm_init hasn't created the L2PTs (and their L1PT entries)
- Add some comments to explain what's going on


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/arm/arm/armv6_start.S
cvs rdiff -u -r1.64 -r1.65 src/sys/arch/arm/arm32/arm32_kvminit.c
cvs rdiff -u -r1.94 -r1.95 src/sys/arch/arm/arm32/genassym.cf
cvs rdiff -u -r1.42 -r1.43 src/sys/arch/arm/arm32/locore.S
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/include/asan.h
cvs rdiff -u -r1.34 -r1.35 src/sys/arch/arm/include/arm32/machdep.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/arm/arm/armv6_start.S
diff -u src/sys/arch/arm/arm/armv6_start.S:1.26 src/sys/arch/arm/arm/armv6_start.S:1.27
--- src/sys/arch/arm/arm/armv6_start.S:1.26	Fri Aug 28 13:15:05 2020
+++ src/sys/arch/arm/arm/armv6_start.S	Fri Aug 28 13:36:52 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: armv6_start.S,v 1.26 2020/08/28 13:15:05 skrll Exp $	*/
+/*	$NetBSD: armv6_start.S,v 1.27 2020/08/28 13:36:52 skrll Exp $	*/
 
 /*-
  * Copyright (c) 2012, 2017, 2018 The NetBSD Foundation, Inc.
@@ -43,9 +43,6 @@
 #include <arm/armreg.h>
 #include "assym.h"
 
-#define INIT_ARM_STACK_SHIFT	10
-#define INIT_ARM_STACK_SIZE	(1 << INIT_ARM_STACK_SHIFT)
-
 #if defined(CONSADDR) && defined(CONADDR)
 #error Only one of CONSADDR and CONADDR should be defined
 #endif
@@ -234,7 +231,7 @@ generic_savevars:
 	.global start_stacks_bottom
 	.global start_stacks_top
 start_stacks_bottom:
-	.space	INIT_ARM_STACK_SIZE * MAXCPUS
+	.space	INIT_ARM_TOTAL_STACK
 start_stacks_top:
 
 	.section "_init_memory", "aw", %nobits

Index: src/sys/arch/arm/arm32/arm32_kvminit.c
diff -u src/sys/arch/arm/arm32/arm32_kvminit.c:1.64 src/sys/arch/arm/arm32/arm32_kvminit.c:1.65
--- src/sys/arch/arm/arm32/arm32_kvminit.c:1.64	Fri Jul 10 12:25:09 2020
+++ src/sys/arch/arm/arm32/arm32_kvminit.c	Fri Aug 28 13:36:52 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: arm32_kvminit.c,v 1.64 2020/07/10 12:25:09 skrll Exp $	*/
+/*	$NetBSD: arm32_kvminit.c,v 1.65 2020/08/28 13:36:52 skrll Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003, 2005  Genetec Corporation.  All rights reserved.
@@ -127,7 +127,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: arm32_kvminit.c,v 1.64 2020/07/10 12:25:09 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: arm32_kvminit.c,v 1.65 2020/08/28 13:36:52 skrll Exp $");
 
 #include <sys/param.h>
 
@@ -184,6 +184,7 @@ vaddr_t kasan_kernelstart;
 vaddr_t kasan_kernelsize;
 
 #define	KERNEL_L2PT_KASAN_NUM	howmany(VM_KERNEL_KASAN_SIZE, L2_S_SEGSIZE)
+bool kasan_l2pts_created  __attribute__((__section__(".data"))) = false;
 pv_addr_t kasan_l2pt[KERNEL_L2PT_KASAN_NUM];
 #else
 #define KERNEL_L2PT_KASAN_NUM	0
@@ -741,6 +742,7 @@ arm32_kernel_vm_init(vaddr_t kernel_vm_b
 		    __func__, kasan_l2pt[idx].pv_va, kasan_l2pt[idx].pv_pa,
 		    va, "(kasan)");
 	}
+	kasan_l2pts_created = true;
 #endif
 
 	/* update the top of the kernel VM */

Index: src/sys/arch/arm/arm32/genassym.cf
diff -u src/sys/arch/arm/arm32/genassym.cf:1.94 src/sys/arch/arm/arm32/genassym.cf:1.95
--- src/sys/arch/arm/arm32/genassym.cf:1.94	Fri Aug 14 16:18:36 2020
+++ src/sys/arch/arm/arm32/genassym.cf	Fri Aug 28 13:36:52 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.94 2020/08/14 16:18:36 skrll Exp $
+#	$NetBSD: genassym.cf,v 1.95 2020/08/28 13:36:52 skrll Exp $
 
 # Copyright (c) 1982, 1990 The Regents of the University of California.
 # All rights reserved.
@@ -58,6 +58,7 @@ include <arm/locore.h>
 include <arm/vfpreg.h>
 include <arm/undefined.h>
 
+include <arm/arm32/machdep.h>
 include <arm/arm32/pte.h>
 
 include <machine/pmap.h>
@@ -160,6 +161,10 @@ define	MAXCPUS			MAXCPUS
 #define	CPU_CONTROL_DC_ENABLE	CPU_CONTROL_DC_ENABLE
 #define	TTBCR_S_PD0		TTBCR_S_PD0
 
+define	INIT_ARM_STACK_SHIFT	INIT_ARM_STACK_SHIFT
+define	INIT_ARM_STACK_SIZE	INIT_ARM_STACK_SIZE
+define	INIT_ARM_TOTAL_STACK	INIT_ARM_TOTAL_STACK
+
 # Important offsets into the lwp and proc structs & associated constants
 define	L_PCB			offsetof(struct lwp, l_addr)
 define	L_CPU			offsetof(struct lwp, l_cpu)

Index: src/sys/arch/arm/arm32/locore.S
diff -u src/sys/arch/arm/arm32/locore.S:1.42 src/sys/arch/arm/arm32/locore.S:1.43
--- src/sys/arch/arm/arm32/locore.S:1.42	Fri Aug 28 12:31:44 2020
+++ src/sys/arch/arm/arm32/locore.S	Fri Aug 28 13:36:52 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.42 2020/08/28 12:31:44 skrll Exp $	*/
+/*	$NetBSD: locore.S,v 1.43 2020/08/28 13:36:52 skrll Exp $	*/
 
 /*
  * Copyright (C) 1994-1997 Mark Brinicombe
@@ -40,10 +40,7 @@
 #include <arm/asm.h>
 #include <arm/locore.h>
 
-/* What size should this really be ? It is only used by initarm() */
-#define INIT_ARM_STACK_SIZE	2048
-
-	RCSID("$NetBSD: locore.S,v 1.42 2020/08/28 12:31:44 skrll Exp $")
+	RCSID("$NetBSD: locore.S,v 1.43 2020/08/28 13:36:52 skrll Exp $")
 
 /*
  * This is for kvm_mkdb, and should be the address of the beginning
@@ -137,6 +134,7 @@ ASEND(start)
 #ifdef __ARM_EABI__
 	.align	3
 #endif
+/* What size should this really be ? It is only used by initarm() */
 svcstk:
 	.space	INIT_ARM_STACK_SIZE
 svcstk_end:

Index: src/sys/arch/arm/include/asan.h
diff -u src/sys/arch/arm/include/asan.h:1.3 src/sys/arch/arm/include/asan.h:1.4
--- src/sys/arch/arm/include/asan.h:1.3	Sun Jul 19 11:47:48 2020
+++ src/sys/arch/arm/include/asan.h	Fri Aug 28 13:36:52 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: asan.h,v 1.3 2020/07/19 11:47:48 skrll Exp $	*/
+/*	$NetBSD: asan.h,v 1.4 2020/08/28 13:36:52 skrll Exp $	*/
 
 /*
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -62,9 +62,24 @@ kasan_md_unsupported(vaddr_t addr)
  * that VA = PA + KERNEL_BASE.
  */
 
-#define KASAN_NEARLYPAGES	3
+/*
+ * KASAN_NEARLYPAGES is hard to work out.
+ *
+ * The INIT_ARM_TOTAL_STACK shadow is reduced by the KASAN_SHADOW_SCALE_SIZE
+ * factor. This shadow mapping is likely to span more than one L2 page tables
+ * and, as a result, more than one PAGE_SIZE block. The L2 page tables might
+ * span more than one L1 page table entry as well.
+ *
+ * To ensure we have enough start with the assumption of 1 L1 page table, and
+ * the number of pages to map the shadow... then double for the spanning as
+ * described above
+ */
+
+#define KASAN_NEARLYPAGES	\
+    (2 * (1 + howmany(INIT_ARM_TOTAL_STACK / KASAN_SHADOW_SCALE_SIZE, PAGE_SIZE)))
 
 static bool __md_early __read_mostly;
+static size_t __md_nearlyl1pts __attribute__((__section__(".data"))) = 0;
 static size_t __md_nearlypages __attribute__((__section__(".data")));
 static uint8_t __md_earlypages[KASAN_NEARLYPAGES * PAGE_SIZE]
     __aligned(PAGE_SIZE)  __attribute__((__section__(".data")));
@@ -115,22 +130,9 @@ kasan_md_shadow_map_page(vaddr_t va)
 	vaddr_t l2ptva;
 
 	KASSERT((va & PAGE_MASK) == 0);
-	KASSERT(__md_early || l1pte_page_p(pdep[l1slot]));
 
-	if (!l1pte_page_p(pdep[l1slot])) {
-		KASSERT(__md_early);
-		const paddr_t l2ptpa = __md_palloc();
-		const vaddr_t segl2va = va & -L2_S_SEGSIZE;
-		const size_t segl1slot = l1pte_index(segl2va);
-
-		const pd_entry_t npde =
-		    L1_C_PROTO | l2ptpa | L1_C_DOM(PMAP_DOMAIN_KERNEL);
-
-		l1pte_set(pdep + segl1slot, npde);
-		PDE_SYNC_RANGE(pdep, PAGE_SIZE / L2_T_SIZE);
-
-		l2ptva = KERN_PHYSTOV(l1pte_pa(pdep[l1slot]));
-	} else {
+	extern bool kasan_l2pts_created;
+	if (__predict_true(kasan_l2pts_created)) {
 		/*
 		 * The shadow map area L2PTs were allocated and mapped
 		 * by arm32_kernel_vm_init.  Use the array of pv_addr_t
@@ -142,6 +144,29 @@ kasan_md_shadow_map_page(vaddr_t va)
 		const size_t idx = off / L2_S_SEGSIZE;
 		const vaddr_t segl2ptva = kasan_l2pt[idx].pv_va;
 		l2ptva = segl2ptva + l1pte_index(segoff) * L2_TABLE_SIZE_REAL;
+	} else {
+		/*
+		 * An L1PT entry is/may be required for bootstrap tables.  As a
+		 * page gives enough space to multiple L2PTs the previous call
+		 * might have already created the L2PT.
+		 */
+		if (!l1pte_page_p(pdep[l1slot])) {
+			const paddr_t l2ptpa = __md_palloc();
+			const vaddr_t segl2va = va & -L2_S_SEGSIZE;
+			const size_t segl1slot = l1pte_index(segl2va);
+
+			__md_nearlyl1pts++;
+
+			const pd_entry_t npde =
+			    L1_C_PROTO | l2ptpa | L1_C_DOM(PMAP_DOMAIN_KERNEL);
+
+			l1pte_set(pdep + segl1slot, npde);
+			/*
+			 * No need for PDE_SYNC_RANGE here as we're creating
+			 * the bootstrap tables
+			*/
+		}
+		l2ptva = KERN_PHYSTOV(l1pte_pa(pdep[l1slot]));
 	}
 
 	pt_entry_t * l2pt = (pt_entry_t *)l2ptva;
@@ -153,11 +178,13 @@ kasan_md_shadow_map_page(vaddr_t va)
 		pt_entry_t npte =
 		    L2_S_PROTO |
 		    pa |
-		    pte_l2_s_cache_mode_pt |
+		    (__md_early ? 0 : pte_l2_s_cache_mode_pt) |
 		    L2_S_PROT(PTE_KERNEL, prot);
-
 		l2pte_set(ptep, npte, 0);
-		PTE_SYNC(ptep);
+
+		if (!__md_early)
+			PTE_SYNC(ptep);
+
 		__builtin_memset((void *)va, 0, PAGE_SIZE);
 	}
 }
@@ -165,16 +192,22 @@ kasan_md_shadow_map_page(vaddr_t va)
 /*
  * Map the init stacks of the BP and APs. We will map the rest in kasan_init.
  */
-#define INIT_ARM_STACK_SHIFT	10
-#define INIT_ARM_STACK_SIZE	(1 << INIT_ARM_STACK_SHIFT)
-
 static void
 kasan_md_early_init(void *stack)
 {
 
+	/*
+	 * We come through here twice.  The first time is for generic_start
+	 * and the bootstrap tables.  The second is for arm32_kernel_vm_init
+	 * and the real tables.
+	 *
+	 * In the first we have to create L1PT entries, whereas in the
+	 * second arm32_kernel_vm_init has setup kasan_l1pts (and the L1PT
+	 * entries for them
+	 */
 	__md_early = true;
-	__md_nearlypages = 0;
-	kasan_shadow_map(stack, INIT_ARM_STACK_SIZE * MAXCPUS);
+	__md_nearlypages = __md_nearlyl1pts;
+	kasan_shadow_map(stack, INIT_ARM_TOTAL_STACK);
 	__md_early = false;
 }
 

Index: src/sys/arch/arm/include/arm32/machdep.h
diff -u src/sys/arch/arm/include/arm32/machdep.h:1.34 src/sys/arch/arm/include/arm32/machdep.h:1.35
--- src/sys/arch/arm/include/arm32/machdep.h:1.34	Sat Jul  4 07:02:35 2020
+++ src/sys/arch/arm/include/arm32/machdep.h	Fri Aug 28 13:36:52 2020
@@ -1,10 +1,14 @@
-/* $NetBSD: machdep.h,v 1.34 2020/07/04 07:02:35 skrll Exp $ */
+/* $NetBSD: machdep.h,v 1.35 2020/08/28 13:36:52 skrll Exp $ */
 
 #ifndef _ARM32_MACHDEP_H_
 #define _ARM32_MACHDEP_H_
 
 #ifdef _KERNEL
 
+#define INIT_ARM_STACK_SHIFT	12
+#define INIT_ARM_STACK_SIZE	(1 << INIT_ARM_STACK_SHIFT)
+#define INIT_ARM_TOTAL_STACK	(INIT_ARM_STACK_SIZE * MAXCPUS)
+
 /* Define various stack sizes in pages */
 #ifndef IRQ_STACK_SIZE
 #define IRQ_STACK_SIZE	1

Reply via email to