summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2014-12-21 16:27:09 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2014-12-21 16:27:09 +0000
commit150a3f578c6b989cb035e5529c23c2c7fbeb0ecc (patch)
tree8ee536e92f7dfa6fc1e83b637acb3c9e0e7786be
parent6392d14dd0230c01c3c1b5127edee7472380e352 (diff)
Prevent writing to the kernel area via the direct map. We do this by padding
the end of the kernel area to 2MB, so that the direct map pages can then have the W permission removed (X permission was already removed in a previous diff). This creates a VA hole at the end of bss, so adjust for that since that's where symbols get loaded by the bootloader (for now, map that region RO until the boot loader can be updated to place the symbols at "end" instead of "end of bss"). with help from and ok deraadt@
-rw-r--r--sys/arch/amd64/amd64/locore.S65
-rw-r--r--sys/arch/amd64/amd64/machdep.c4
-rw-r--r--sys/arch/amd64/conf/ld.script14
-rw-r--r--sys/ddb/db_sym.c6
4 files changed, 66 insertions, 23 deletions
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index eeecb1157b1..022cd07ef38 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.60 2014/11/27 17:35:12 mlarkin Exp $ */
+/* $OpenBSD: locore.S,v 1.61 2014/12/21 16:27:07 mlarkin Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -174,7 +174,7 @@ _C_LABEL(lapic_isr):
.globl _C_LABEL(cpu_perf_ebx)
.globl _C_LABEL(cpu_perf_edx)
.globl _C_LABEL(cpu_apmi_edx)
- .globl _C_LABEL(esym),_C_LABEL(boothowto),_C_LABEL(bootdev)
+ .globl _C_LABEL(ssym),_C_LABEL(esym),_C_LABEL(boothowto),_C_LABEL(bootdev)
.globl _C_LABEL(bootinfo), _C_LABEL(bootinfo_size), _C_LABEL(atdevbase)
.globl _C_LABEL(proc0paddr),_C_LABEL(PTDpaddr)
.globl _C_LABEL(biosbasemem),_C_LABEL(biosextmem)
@@ -196,6 +196,7 @@ _C_LABEL(cpuid_level): .long -1 # max. level accepted by 'cpuid'
_C_LABEL(cpu_vendor): .space 16 # vendor string returned by `cpuid'
# instruction
_C_LABEL(cpu_brand_id): .long 0 # brand ID from 'cpuid' instruction
+_C_LABEL(ssym): .quad 0 # ptr to start of syms
_C_LABEL(esym): .quad 0 # ptr to end of syms
_C_LABEL(atdevbase): .quad 0 # location of start of iomem in virtual
_C_LABEL(bootapiver): .long 0 # /boot API version
@@ -474,14 +475,46 @@ cont:
orl $(PG_V|PG_KR), %eax
fillkpt_nx
- /* Reload %edx for data_start */
- movl $RELOC(__data_start), %edx
+ /* Map the data and BSS sections RW, NX */
+ movl $RELOC(__data_start), %eax
+ movl $RELOC(__kernel_bss_end),%ecx
+ addl $PGOFSET, %ecx
+ andl $~PGOFSET, %ecx
+ subl %eax, %ecx
+ shrl $PGSHIFT,%ecx
+ orl $(PG_V|PG_KW), %eax
+ fillkpt_nx
- /* Map the data, BSS, and bootstrap tables RW, NX */
+ /* Map "hole" at end of BSS RO, NX */
+ movl $RELOC(__kernel_bss_end), %eax
+ movl $RELOC(end), %ecx
+ addl $PGOFSET, %ecx
+ andl $~PGOFSET, %ecx
+ cmpl %eax, %ecx
+ je map_syms
+ subl %eax, %ecx
+ shrl $PGSHIFT, %ecx
+ orl $(PG_V|PG_KR), %eax
+ fillkpt_nx
+
+map_syms:
+ /* Map symbol space RO, NX */
+ movl $RELOC(end), %eax
+ movl %esi, %ecx
+ addl $PGOFSET, %ecx
+ andl $~PGOFSET, %ecx
+ cmpl %eax, %ecx
+ je map_tables
+ subl %eax, %ecx
+ shrl $PGSHIFT, %ecx
+ orl $(PG_V|PG_KR), %eax
+ fillkpt_nx
+
+map_tables:
+ /* Map the bootstrap tables RW, NX */
+ movl %esi, %edx
leal (PG_V|PG_KW)(%edx),%eax
movl $TABLESIZE,%ecx
- addl %esi,%ecx /* %ecx = end + TABLESIZE */
- subl %edx,%ecx /* %ecx = %ecx - data_start */
shrl $PGSHIFT,%ecx
fillkpt_nx
@@ -539,13 +572,22 @@ cont:
/*
* Map the first 4 GB with the direct map. We'll map the rest
* in pmap_bootstrap. But we always need the first 4GB during
- * bootstrap. The direct map is mapped RW, NX.
+ * bootstrap. The direct map is mapped RW, NX. We also change
+ * the permissions on the 2MB pages corresponding to the kernel
+ * PAs to RO to prevent someone writing to the kernel area
+ * via the direct map.
*/
leal (PROC0_DMP2_OFF)(%esi), %ebx
xorl %eax, %eax
- orl $(PG_V|PG_KW|PG_PS|PG_G), %eax
movl $(NDML2_ENTRIES * NPDPG), %ecx
-1: movl %eax, (%ebx)
+1: orl $(PG_V|PG_KW|PG_PS|PG_G), %eax
+ cmpl $__kernel_base_phys, %eax
+ jl store_pte
+ cmpl $__kernel_end_phys, %eax
+ jg store_pte
+ andl $(~PG_KW), %eax
+store_pte:
+ movl %eax, (%ebx)
pushl %ebp
movl RELOC((pg_nx + 4)), %ebp
movl %ebp, 4(%ebx)
@@ -681,6 +723,9 @@ longmode_hi:
addq %rsi,%rdx
movq %rdx,_C_LABEL(atdevbase)(%rip)
+ /* Record start of symbols */
+ movq $__kernel_bss_end, _C_LABEL(ssym)(%rip)
+
/* Set up bootstrap stack. */
leaq (PROC0_STK_OFF)(%rsi),%rax
addq %r8,%rax
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index d1a6fdd4276..53402f706fb 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.203 2014/12/18 05:33:48 mlarkin Exp $ */
+/* $OpenBSD: machdep.c,v 1.204 2014/12/21 16:27:07 mlarkin Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -177,8 +177,6 @@ paddr_t dumpmem_paddr;
vaddr_t dumpmem_vaddr;
psize_t dumpmem_sz;
-
-char *ssym = NULL;
vaddr_t kern_end;
vaddr_t msgbuf_vaddr;
diff --git a/sys/arch/amd64/conf/ld.script b/sys/arch/amd64/conf/ld.script
index 4dc06ff4c0e..15178e33788 100644
--- a/sys/arch/amd64/conf/ld.script
+++ b/sys/arch/amd64/conf/ld.script
@@ -1,4 +1,4 @@
-/* $OpenBSD: ld.script,v 1.1 2014/11/18 01:11:13 deraadt Exp $ */
+/* $OpenBSD: ld.script,v 1.2 2014/12/21 16:27:07 mlarkin Exp $ */
/*
* Copyright (c) 2009 Tobias Weingartner <weingart@tepid.org>
@@ -104,16 +104,16 @@ SECTIONS
__bss_load = LOADADDR(.bss);
*(.bss .bss.*)
*(COMMON)
- /* Align here to ensure that the .bss section occupies space
- * up to _end. Align after .bss to ensure correct alignment
- * even if the .bss section disappears because there are no
- * input sections.
+ /* Align after .bss to ensure correct alignment even if the
+ * .bss section disappears because there are no input sections.
*/
- . = ALIGN(64 / 8);
+ . = ALIGN(0x1000);
} :bss
- . = ALIGN(64 / 8);
+ __kernel_bss_end = .;
+ . = ALIGN(0x200000);
_end = .;
PROVIDE (end = .);
+ __kernel_end_phys = . & 0x7fffffff;
/* XXX - hack alert, since we are not C++, nuke these */
/DISCARD/ :
diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c
index 934fe22dce5..5c209778f85 100644
--- a/sys/ddb/db_sym.c
+++ b/sys/ddb/db_sym.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_sym.c,v 1.35 2014/09/14 14:17:24 jsg Exp $ */
+/* $OpenBSD: db_sym.c,v 1.36 2014/12/21 16:27:08 mlarkin Exp $ */
/* $NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $ */
/*
@@ -121,13 +121,13 @@ ddb_init(void)
const db_symformat_t **symf;
const char *name = "bsd";
extern char *esym;
-#if defined(__sparc64__) || defined(__mips__)
+#if defined(__sparc64__) || defined(__mips__) || defined(__amd64__)
extern char *ssym;
#endif
char *xssym, *xesym;
xesym = esym;
-#if defined(__sparc64__) || defined(__mips__)
+#if defined(__sparc64__) || defined(__mips__) || defined(__amd64__)
xssym = ssym;
#else
xssym = (char *)&end;