Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/aarch64 set kernel text/rodata readonly by default.



details:   https://anonhg.NetBSD.org/src/rev/828e45ab0a89
branches:  trunk
changeset: 834294:828e45ab0a89
user:      ryo <ryo%NetBSD.org@localhost>
date:      Mon Aug 06 12:50:56 2018 +0000

description:
set kernel text/rodata readonly by default.
add function db_write_text() for setting ddb breakpoint.

diffstat:

 sys/arch/aarch64/aarch64/db_interface.c |  68 ++++++++++++++++++++++++-
 sys/arch/aarch64/aarch64/locore.S       |   6 +-
 sys/arch/aarch64/aarch64/pmap.c         |  88 ++++++++++++++++++++++++++++++++-
 sys/arch/aarch64/include/pmap.h         |   6 +-
 4 files changed, 159 insertions(+), 9 deletions(-)

diffs (268 lines):

diff -r 87dd66bab82f -r 828e45ab0a89 sys/arch/aarch64/aarch64/db_interface.c
--- a/sys/arch/aarch64/aarch64/db_interface.c   Mon Aug 06 08:05:32 2018 +0000
+++ b/sys/arch/aarch64/aarch64/db_interface.c   Mon Aug 06 12:50:56 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.4 2018/06/03 20:18:10 christos Exp $ */
+/* $NetBSD: db_interface.c,v 1.5 2018/08/06 12:50:56 ryo Exp $ */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,16 +27,18 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.4 2018/06/03 20:18:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.5 2018/08/06 12:50:56 ryo Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
 
 #include <uvm/uvm.h>
+#include <uvm/uvm_prot.h>
 
 #include <aarch64/db_machdep.h>
 #include <aarch64/machdep.h>
 #include <aarch64/pmap.h>
+#include <aarch64/cpufunc.h>
 
 #include <ddb/db_access.h>
 #include <ddb/db_command.h>
@@ -88,12 +90,74 @@
        }
 }
 
+static void
+db_write_text(vaddr_t addr, size_t size, const char *data)
+{
+       pt_entry_t *ptep, pte;
+       size_t s;
+
+       /*
+        * consider page boundary, and
+        * it works even if kernel_text is mapped with L2 or L3.
+        */
+       if (atop(addr) != atop(addr + size - 1)) {
+               s = PAGE_SIZE - (addr & PAGE_MASK);
+               db_write_text(addr, s, data);
+               addr += s;
+               size -= s;
+               data += s;
+       }
+       while (size > 0) {
+               ptep = kvtopte(addr);
+               KASSERT(ptep != NULL);
+
+               /* save pte */
+               pte = *ptep;
+
+               /* change to writable */
+               pmap_kvattr(addr, VM_PROT_READ|VM_PROT_WRITE);
+               aarch64_tlbi_all();
+
+               s = size;
+               if (size > PAGE_SIZE)
+                       s = PAGE_SIZE;
+
+               memcpy((void *)addr, data, s);
+               cpu_icache_sync_range(addr, size);
+
+               /* restore pte */
+               *ptep = pte;
+               aarch64_tlbi_all();
+
+               addr += s;
+               size -= s;
+               data += s;
+       }
+}
+
 void
 db_write_bytes(vaddr_t addr, size_t size, const char *data)
 {
+       vaddr_t kernstart, datastart;
        vaddr_t lastpage = -1;
        char *dst;
 
+       /* if readonly page, require changing attribute to write */
+       extern char __kernel_text[], __data_start[];
+       kernstart = trunc_page((vaddr_t)__kernel_text);
+       datastart = trunc_page((vaddr_t)__data_start);
+       if (kernstart <= addr && addr < datastart) {
+               size_t s;
+
+               s = datastart - addr;
+               if (s > size)
+                       s = size;
+               db_write_text(addr, s, data);
+               addr += s;
+               size -= s;
+               data += s;
+       }
+
        /* XXX: need to check read only block/page */
        for (dst = (char *)addr; size > 0;) {
                uintptr_t tmp;
diff -r 87dd66bab82f -r 828e45ab0a89 sys/arch/aarch64/aarch64/locore.S
--- a/sys/arch/aarch64/aarch64/locore.S Mon Aug 06 08:05:32 2018 +0000
+++ b/sys/arch/aarch64/aarch64/locore.S Mon Aug 06 12:50:56 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.14 2018/08/03 16:32:55 ryo Exp $  */
+/*     $NetBSD: locore.S,v 1.15 2018/08/06 12:50:56 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.14 2018/08/03 16:32:55 ryo Exp $")
+RCSID("$NetBSD: locore.S,v 1.15 2018/08/06 12:50:56 ryo Exp $")
 
 /* #define DEBUG_LOCORE */
 /* #define DEBUG_MMU */
@@ -650,7 +650,6 @@
        lsr     x4, x4, #L2_SHIFT
        bl      l2_setblocks
 
-#ifndef DDB
        /* map READONLY from VM_MIN_KERNEL_ADDRESS to __data_start */
        VERBOSE("Set kernel text/rodata READONLY\r\n")
        ldr     x3, =__data_start
@@ -684,7 +683,6 @@
 9:
        cmp     x2, x3
        blo     1b
-#endif
 
        VERBOSE("Creating devmap tables\r\n")
        /* devmap=PA table for L1 */
diff -r 87dd66bab82f -r 828e45ab0a89 sys/arch/aarch64/aarch64/pmap.c
--- a/sys/arch/aarch64/aarch64/pmap.c   Mon Aug 06 08:05:32 2018 +0000
+++ b/sys/arch/aarch64/aarch64/pmap.c   Mon Aug 06 12:50:56 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.16 2018/07/31 07:00:48 skrll Exp $  */
+/*     $NetBSD: pmap.c,v 1.17 2018/08/06 12:50:56 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.16 2018/07/31 07:00:48 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.17 2018/08/06 12:50:56 ryo Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_ddb.h"
@@ -1990,6 +1990,90 @@
 }
 
 #ifdef DDB
+/* get pointer to kernel segment L2 or L3 table entry */
+pt_entry_t *
+kvtopte(vaddr_t va)
+{
+       pd_entry_t *l0, *l1, *l2, *l3;
+       pd_entry_t pde;
+       pt_entry_t *ptep;
+       unsigned int idx;
+
+       KASSERT(VM_MIN_KERNEL_ADDRESS <= va && va < VM_MAX_KERNEL_ADDRESS);
+
+       /*
+        * traverse L0 -> L1 -> L2 block (or -> L3 table)
+        */
+       l0 = pmap_kernel()->pm_l0table;
+
+       idx = l0pde_index(va);
+       pde = l0[idx];
+       if (!l0pde_valid(pde))
+               return NULL;
+
+       l1 = (void *)AARCH64_PA_TO_KVA(l0pde_pa(pde));
+       idx = l1pde_index(va);
+       pde = l1[idx];
+       if (!l1pde_valid(pde))
+               return NULL;
+
+       if (l1pde_is_block(pde))
+               return NULL;
+
+       l2 = (void *)AARCH64_PA_TO_KVA(l1pde_pa(pde));
+       idx = l2pde_index(va);
+       pde = l2[idx];
+       if (!l2pde_valid(pde))
+               return NULL;
+       if (l2pde_is_block(pde))
+               return &l2[idx];        /* kernel text/data use L2 blocks */
+
+       l3 = (void *)AARCH64_PA_TO_KVA(l2pde_pa(pde));
+       idx = l3pte_index(va);
+       ptep = &l3[idx];                /* or may use L3 page? */
+
+       return ptep;
+}
+
+/* change attribute of kernel segment */
+pt_entry_t
+pmap_kvattr(vaddr_t va, vm_prot_t prot)
+{
+       pt_entry_t *ptep, pte, opte;
+
+       KASSERT(VM_MIN_KERNEL_ADDRESS <= va && va < VM_MAX_KERNEL_ADDRESS);
+
+       ptep = kvtopte(va);
+       if (ptep == NULL)
+               panic("%s: %016lx is not mapped\n", __func__, va);
+
+       opte = pte = *ptep;
+
+       pte &= ~(LX_BLKPAG_AF|LX_BLKPAG_AP);
+       switch (prot & (VM_PROT_READ|VM_PROT_WRITE)) {
+       case 0:
+               break;
+       case VM_PROT_READ:
+               pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RO);
+               break;
+       case VM_PROT_WRITE:
+       case VM_PROT_READ|VM_PROT_WRITE:
+               pte |= (LX_BLKPAG_AF|LX_BLKPAG_AP_RW);
+               break;
+       }
+
+       if ((prot & VM_PROT_EXECUTE) == 0) {
+               pte |= (LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+       } else {
+               pte |= LX_BLKPAG_AF;
+               pte &= ~(LX_BLKPAG_UXN|LX_BLKPAG_PXN);
+       }
+
+       *ptep = pte;
+
+       return opte;
+}
+
 static void
 pmap_db_pte_print(pt_entry_t pte, int level, void (*pr)(const char *, ...))
 {
diff -r 87dd66bab82f -r 828e45ab0a89 sys/arch/aarch64/include/pmap.h
--- a/sys/arch/aarch64/include/pmap.h   Mon Aug 06 08:05:32 2018 +0000
+++ b/sys/arch/aarch64/include/pmap.h   Mon Aug 06 12:50:56 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.6 2018/07/27 07:04:04 ryo Exp $ */
+/* $NetBSD: pmap.h,v 1.7 2018/08/06 12:50:56 ryo Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -107,7 +107,11 @@
 
 void pmap_bootstrap(vaddr_t, vaddr_t);
 bool pmap_fault_fixup(struct pmap *, vaddr_t, vm_prot_t, bool user);
+
+/* for ddb */
 void pmap_db_pteinfo(vaddr_t, void (*)(const char *, ...));
+pt_entry_t *kvtopte(vaddr_t);
+pt_entry_t pmap_kvattr(vaddr_t, vm_prot_t);
 
 /* Hooks for the pool allocator */
 paddr_t vtophys(vaddr_t);



Home | Main Index | Thread Index | Old Index