From 599a5352d9cf80c1cd045c515cf0ac6464b69dad Mon Sep 17 00:00:00 2001 From: deraadt Date: Mon, 5 Jun 2017 17:49:05 +0000 Subject: [PATCH] Split early startup code out of locore.S into locore0.S. Adjust link run so that this locore0.o is always at the start of the executable. But randomize the link order of all other .o files in the kernel, so that their exec/rodata/data/bss segments land all over the place. Late during kernel boot, smash the startup code with traps so that it does not point to the other randomly placed code. It has be smashed, because alpha (insecurely in my view) runs in the KSEG0 space. As a result, the internal layout of every newly build bsd kernel is different from past kernels. Internal relative offsets are not known to an outside attacker. The only known offsets are in the startup code, which is gone. Ramdisk kernels cannot be compiled like this, because they are gzip'd. When the internal pointer references change, the compression dictionary bloats and results in poorer compression. --- sys/arch/alpha/alpha/autoconf.c | 15 ++- sys/arch/alpha/alpha/locore.s | 74 +------------ sys/arch/alpha/alpha/locore0.S | 166 +++++++++++++++++++++++++++++ sys/arch/alpha/conf/Makefile.alpha | 25 +++-- sys/arch/alpha/conf/files.alpha | 3 +- sys/arch/alpha/include/param.h | 4 +- 6 files changed, 205 insertions(+), 82 deletions(-) create mode 100644 sys/arch/alpha/alpha/locore0.S diff --git a/sys/arch/alpha/alpha/autoconf.c b/sys/arch/alpha/alpha/autoconf.c index e24b03c3f84..300f7b90457 100644 --- a/sys/arch/alpha/alpha/autoconf.c +++ b/sys/arch/alpha/alpha/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.36 2016/06/08 17:24:44 tedu Exp $ */ +/* $OpenBSD: autoconf.c,v 1.37 2017/06/05 17:49:05 deraadt Exp $ */ /* $NetBSD: autoconf.c,v 1.16 1996/11/13 21:13:04 cgd Exp $ */ /* @@ -67,6 +67,17 @@ char boot_dev[128]; void parse_prom_bootdev(void); int atoi(char *); +void +unmap_startup(void) +{ + extern uint32_t kernel_text[], endboot[]; + uint32_t *word = kernel_text; + + /* Cannot unmap KSEG0; smash with 0x00000000 (call_pall PAL_halt) */ + while (word < endboot) + *word++ = 0x00000000; +} + /* * cpu_configure: * called at boot time, configure all devices on system @@ -77,6 +88,8 @@ cpu_configure() parse_prom_bootdev(); softintr_init(); + unmap_startup(); + /* * Disable interrupts during autoconfiguration. splhigh() won't * work, because it simply _raises_ the IPL, so if machine checks diff --git a/sys/arch/alpha/alpha/locore.s b/sys/arch/alpha/alpha/locore.s index a55cec33c62..32fc2269025 100644 --- a/sys/arch/alpha/alpha/locore.s +++ b/sys/arch/alpha/alpha/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.46 2017/05/27 14:33:39 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.47 2017/06/05 17:49:05 deraadt Exp $ */ /* $NetBSD: locore.s,v 1.94 2001/04/26 03:10:44 ross Exp $ */ /*- @@ -132,78 +132,6 @@ IMPORT(cpu_info_primary, CPU_INFO_SIZEOF) bne \reg, \dst .endm -/* - * This is for kvm_mkdb, and should be the address of the beginning - * of the kernel text segment (not necessarily the same as kernbase). - */ - EXPORT(kernel_text) -.loc 1 __LINE__ -kernel_text: - -/* - * bootstack: a temporary stack, for booting. - * - * Extends from 'start' down. - */ -bootstack: - -/* - * __start: Kernel start. - * - * Arguments: - * a0 is the first free page frame number (PFN) (no longer used) - * a1 is the page table base register (PTBR) - * a2 is the bootinfo magic number - * a3 is the pointer to the bootinfo structure - * - * All arguments are passed to alpha_init(). - */ -NESTED_NOPROFILE(__start,1,0,ra,0,0) - br pv,Lstart1 -Lstart1: LDGP(pv) - - /* Switch to the boot stack. */ - lda sp,bootstack - - /* Load KGP with current GP. */ - or gp,zero,a0 - call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */ - - /* - * Call alpha_init() to do pre-main initialization. - * alpha_init() gets the arguments we were called with, - * which are already in a0 (destroyed), a1, a2, a3 and a4. - */ - CALL(alpha_init) - - /* Set up the virtual page table pointer. */ - ldiq a0, VPTBASE - call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */ - - /* - * Switch to proc0's PCB. - */ - lda a0, proc0 - ldq a0, P_MD_PCBPADDR(a0) /* phys addr of PCB */ - SWITCH_CONTEXT - - /* - * We've switched to a new page table base, so invalidate the TLB - * and I-stream. This happens automatically everywhere but here. - */ - ldiq a0, -2 /* TBIA */ - call_pal PAL_OSF1_tbi - call_pal PAL_imb - - /* - * All ready to go! Call main()! - */ - CALL(main) - - /* This should never happen. */ - PANIC("main() returned",Lmain_returned_pmsg) - END(__start) - /**************************************************************************/ /* diff --git a/sys/arch/alpha/alpha/locore0.S b/sys/arch/alpha/alpha/locore0.S new file mode 100644 index 00000000000..9c6e5a77617 --- /dev/null +++ b/sys/arch/alpha/alpha/locore0.S @@ -0,0 +1,166 @@ +/* $OpenBSD: locore0.S,v 1.1 2017/06/05 17:49:05 deraadt Exp $ */ +/* $NetBSD: locore.s,v 1.94 2001/04/26 03:10:44 ross Exp $ */ + +/*- + * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +.file 1 __FILE__ + +#include + +#include "assym.h" + +/* + * Perform actions necessary to switch to a new context. The + * hwpcb should be in a0. Clobbers v0, t0, t8..t11, a0. + */ +#define SWITCH_CONTEXT \ + /* Make a note of the context we're running on. */ \ + GET_CURPCB ; \ + stq a0, 0(v0) ; \ + \ + /* Swap in the new context. */ \ + call_pal PAL_OSF1_swpctx + + + /* don't reorder instructions; paranoia. */ + .set noreorder + .text + + .macro bfalse reg, dst + beq \reg, \dst + .endm + + .macro btrue reg, dst + bne \reg, \dst + .endm + +#define GET_CURPCB \ + call_pal PAL_OSF1_rdval ; \ + addq v0, CPU_INFO_CURPCB, v0 + +/* + * This is for kvm_mkdb, and should be the address of the beginning + * of the kernel text segment (not necessarily the same as kernbase). + */ + EXPORT(kernel_text) +.loc 1 __LINE__ +kernel_text: + +/* + * bootstack: a temporary stack, for booting. + * + * Extends from 'start' down. + */ +bootstack: + +/* + * __start: Kernel start. + * + * Arguments: + * a0 is the first free page frame number (PFN) (no longer used) + * a1 is the page table base register (PTBR) + * a2 is the bootinfo magic number + * a3 is the pointer to the bootinfo structure + * + * All arguments are passed to alpha_init(). + */ +NESTED_NOPROFILE(__start,1,0,ra,0,0) + br pv,Lstart1 +Lstart1: LDGP(pv) + + /* Switch to the boot stack. */ + lda sp,bootstack + + /* Load KGP with current GP. */ + or gp,zero,a0 + call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */ + + /* + * Call alpha_init() to do pre-main initialization. + * alpha_init() gets the arguments we were called with, + * which are already in a0 (destroyed), a1, a2, a3 and a4. + */ + CALL(alpha_init) + + /* Set up the virtual page table pointer. */ + ldiq a0, VPTBASE + call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */ + + /* + * Switch to proc0's PCB. + */ + lda a0, proc0 + ldq a0, P_MD_PCBPADDR(a0) /* phys addr of PCB */ + SWITCH_CONTEXT + + /* + * We've switched to a new page table base, so invalidate the TLB + * and I-stream. This happens automatically everywhere but here. + */ + ldiq a0, -2 /* TBIA */ + call_pal PAL_OSF1_tbi + call_pal PAL_imb + + /* + * All ready to go! Call main()! + */ + CALL(main) + + /* This should never happen. */ + PANIC("main() returned",Lmain_returned_pmsg) + END(__start) diff --git a/sys/arch/alpha/conf/Makefile.alpha b/sys/arch/alpha/conf/Makefile.alpha index 468ee699105..fafd19cbf0e 100644 --- a/sys/arch/alpha/conf/Makefile.alpha +++ b/sys/arch/alpha/conf/Makefile.alpha @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.alpha,v 1.97 2017/06/05 12:43:57 deraadt Exp $ +# $OpenBSD: Makefile.alpha,v 1.98 2017/06/05 17:49:06 deraadt Exp $ # For instructions on building kernels consult the config(8) and options(4) # manual pages. @@ -31,9 +31,13 @@ CMACHFLAGS= -mno-fp-regs -Wa,-mev56 CMACHFLAGS+= -fno-builtin-printf -fno-builtin-snprintf \ -fno-builtin-vsnprintf -fno-builtin-log \ -fno-builtin-log2 -fno-builtin-malloc ${NOPIE_FLAGS} +SORTR= sort -R .if ${IDENT:M-DNO_PROPOLICE} CMACHFLAGS+= -fno-stack-protector .endif +.if ${IDENT:M-DSMALL_KERNEL} +SORTR= cat +.endif DEBUG?= -g COPTS?= -O2 @@ -67,13 +71,14 @@ NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< # ${SYSTEM_LD_HEAD} # ${SYSTEM_LD} swapxxx.o # ${SYSTEM_LD_TAIL} -SYSTEM_HEAD= locore.o param.o ioconf.o -SYSTEM_OBJ= ${SYSTEM_HEAD} ${OBJS} +SYSTEM_HEAD= locore0.o gap.o +SYSTEM_OBJ= ${SYSTEM_HEAD} ${OBJS} param.o ioconf.o SYSTEM_DEP= Makefile ${SYSTEM_OBJ} ld.script SYSTEM_LD_HEAD= @rm -f $@ SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_HEAD} vers.o $${OBJS}'; \ umask 007; \ - ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} vers.o ${OBJS} + echo ${OBJS} param.o ioconf.o vers.o | tr " " "\n" | ${SORTR} > lorder; \ + ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} `cat lorder` SYSTEM_LD_TAIL= @${SIZE} $@ .if ${DEBUG} == "-g" @@ -120,8 +125,15 @@ vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} sh $S/conf/newvers.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c +gap.S: ${SYSTEM_SWAP_DEP} Makefile + umask 007; sh $S/conf/makegap.sh 0x00 > gap.S + +gap.o: gap.S + umask 007; ${CC} ${AFLAGS} ${CPPFLAGS} ${PROF} -c gap.S + clean: - rm -f *bsd *bsd.gdb *.[dio] [a-z]*.s assym.* ${DB_STRUCTINFO} param.c + rm -f *bsd *bsd.gdb *.[dio] [a-z]*.s assym.* ${DB_STRUCTINFO} \ + gap.S lorder param.c cleandir: clean rm -f Makefile *.h ioconf.c options machine ${_mach} vers.c @@ -133,6 +145,7 @@ db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl objdump -g db_structinfo.o | perl $S/ddb/parse_structinfo.pl > $@ rm -f db_structinfo.o +locore0.o: ${_machdir}/${_mach}/locore0.S assym.h locore.o: ${_machdir}/${_mach}/locore.s assym.h # The install target can be redefined by putting a @@ -142,7 +155,7 @@ install: install-kernel-${MACHINE_NAME} .if !target(install-kernel-${MACHINE_NAME}}) install-kernel-${MACHINE_NAME}: cmp -s bsd /bsd || ln -f /bsd /obsd - cp bsd /nbsd + cp -p bsd /nbsd mv /nbsd /bsd .endif diff --git a/sys/arch/alpha/conf/files.alpha b/sys/arch/alpha/conf/files.alpha index 524be16ac72..b4edb201c66 100644 --- a/sys/arch/alpha/conf/files.alpha +++ b/sys/arch/alpha/conf/files.alpha @@ -1,4 +1,4 @@ -# $OpenBSD: files.alpha,v 1.103 2016/01/08 15:54:12 jcs Exp $ +# $OpenBSD: files.alpha,v 1.104 2017/06/05 17:49:06 deraadt Exp $ # $NetBSD: files.alpha,v 1.32 1996/11/25 04:03:21 cgd Exp $ # # alpha-specific configuration info @@ -297,6 +297,7 @@ file arch/alpha/alpha/ipifuncs.c multiprocessor file arch/alpha/alpha/lock_machdep.c multiprocessor file arch/alpha/alpha/machdep.c file arch/alpha/alpha/mainbus.c +file arch/alpha/alpha/locore.s file arch/alpha/alpha/mem.c file arch/alpha/alpha/pmap.c file arch/alpha/alpha/process_machdep.c diff --git a/sys/arch/alpha/include/param.h b/sys/arch/alpha/include/param.h index 07f02070545..ee57f83f50c 100644 --- a/sys/arch/alpha/include/param.h +++ b/sys/arch/alpha/include/param.h @@ -1,4 +1,4 @@ -/* $OpenBSD: param.h,v 1.40 2016/09/03 14:25:27 bluhm Exp $ */ +/* $OpenBSD: param.h,v 1.41 2017/06/05 17:49:06 deraadt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -43,9 +43,11 @@ #define MACHINE_ARCH "alpha" #define MID_MACHINE MID_ALPHA +#ifndef _LOCORE #ifdef _KERNEL #include #endif +#endif #define PAGE_SHIFT 13 #define PAGE_SIZE (1 << PAGE_SHIFT) -- 2.20.1