Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm Some KASAN fixes and tweaks



details:   https://anonhg.NetBSD.org/src/rev/b18ed02b1181
branches:  trunk
changeset: 937884:b18ed02b1181
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Aug 28 13:36:52 2020 +0000

description:
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

diffstat:

 sys/arch/arm/arm/armv6_start.S       |   7 +--
 sys/arch/arm/arm32/arm32_kvminit.c   |   6 +-
 sys/arch/arm/arm32/genassym.cf       |   7 ++-
 sys/arch/arm/arm32/locore.S          |   8 +--
 sys/arch/arm/include/arm32/machdep.h |   6 ++-
 sys/arch/arm/include/asan.h          |  83 +++++++++++++++++++++++++----------
 6 files changed, 78 insertions(+), 39 deletions(-)

diffs (273 lines):

diff -r 849680816be8 -r b18ed02b1181 sys/arch/arm/arm/armv6_start.S
--- a/sys/arch/arm/arm/armv6_start.S    Fri Aug 28 13:15:05 2020 +0000
+++ b/sys/arch/arm/arm/armv6_start.S    Fri Aug 28 13:36:52 2020 +0000
@@ -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 @@
        .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
diff -r 849680816be8 -r b18ed02b1181 sys/arch/arm/arm32/arm32_kvminit.c
--- a/sys/arch/arm/arm32/arm32_kvminit.c        Fri Aug 28 13:15:05 2020 +0000
+++ b/sys/arch/arm/arm32/arm32_kvminit.c        Fri Aug 28 13:36:52 2020 +0000
@@ -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_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 @@
                    __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 */
diff -r 849680816be8 -r b18ed02b1181 sys/arch/arm/arm32/genassym.cf
--- a/sys/arch/arm/arm32/genassym.cf    Fri Aug 28 13:15:05 2020 +0000
+++ b/sys/arch/arm/arm32/genassym.cf    Fri Aug 28 13:36:52 2020 +0000
@@ -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/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        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)
diff -r 849680816be8 -r b18ed02b1181 sys/arch/arm/arm32/locore.S
--- a/sys/arch/arm/arm32/locore.S       Fri Aug 28 13:15:05 2020 +0000
+++ b/sys/arch/arm/arm32/locore.S       Fri Aug 28 13:36:52 2020 +0000
@@ -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 @@
 #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:
diff -r 849680816be8 -r b18ed02b1181 sys/arch/arm/include/arm32/machdep.h
--- a/sys/arch/arm/include/arm32/machdep.h      Fri Aug 28 13:15:05 2020 +0000
+++ b/sys/arch/arm/include/arm32/machdep.h      Fri Aug 28 13:36:52 2020 +0000
@@ -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
diff -r 849680816be8 -r b18ed02b1181 sys/arch/arm/include/asan.h
--- a/sys/arch/arm/include/asan.h       Fri Aug 28 13:15:05 2020 +0000
+++ b/sys/arch/arm/include/asan.h       Fri Aug 28 13:36:52 2020 +0000
@@ -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 @@
  * 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 @@
        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 @@
                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 @@
                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);
 
-               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 @@
 /*
  * 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;
 }
 



Home | Main Index | Thread Index | Old Index