From e8dad7d80fee101871148bbec4c7a8712708ea02 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 19 Mar 2023 20:32:13 +0000 Subject: [PATCH] Aggressively randomize the location of the stack on all 64-bit architectures except alpha. This will put the stack at a random location in the upper 1/4th of the userland virtual address space providing up to 26 additional bits of randomness in the address. Skip alpha for now since it currently puts the stack at a (for a 64-bit architecture) very low address. Skip 32-bit architectures for now as well since those have a much smaller virtual address space and we need more time to figure out what a safe amount of extra randomizations is. These architectures will continue to use a mildly randomized stack address through the existing stackgap random mechanism. We will revisit this after 7.3 is released. This should make it harder for an attacker to find the stack. ok deraadt@, miod@ --- sys/arch/amd64/include/vmparam.h | 5 ++++- sys/arch/arm64/include/vmparam.h | 5 ++++- sys/arch/mips64/include/vmparam.h | 5 ++++- sys/arch/powerpc64/include/vmparam.h | 3 +++ sys/arch/riscv64/include/vmparam.h | 5 ++++- sys/arch/sparc64/include/vmparam.h | 5 ++++- sys/kern/exec_subr.c | 26 +++++++++++++++++--------- 7 files changed, 40 insertions(+), 14 deletions(-) diff --git a/sys/arch/amd64/include/vmparam.h b/sys/arch/amd64/include/vmparam.h index fae0eeec8bd..d7b606a1bf6 100644 --- a/sys/arch/amd64/include/vmparam.h +++ b/sys/arch/amd64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.22 2019/01/03 18:59:27 deraadt Exp $ */ +/* $OpenBSD: vmparam.h,v 1.23 2023/03/19 20:32:13 kettenis Exp $ */ /* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ /*- @@ -94,6 +94,9 @@ #define VM_MIN_ADDRESS PAGE_SIZE #define VM_MAXUSER_ADDRESS 0x00007f7fffffc000 #define VM_MAX_ADDRESS 0x00007fbfdfeff000 +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS 0x0000600000000000 +#endif #define VM_MIN_KERNEL_ADDRESS 0xffff800000000000 #define VM_MAX_KERNEL_ADDRESS 0xffff800100000000 diff --git a/sys/arch/arm64/include/vmparam.h b/sys/arch/arm64/include/vmparam.h index 118fa0ed0a2..af4f674efd6 100644 --- a/sys/arch/arm64/include/vmparam.h +++ b/sys/arch/arm64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.7 2019/06/01 18:38:27 patrick Exp $ */ +/* $OpenBSD: vmparam.h,v 1.8 2023/03/19 20:32:13 kettenis Exp $ */ /* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ /*- @@ -92,6 +92,9 @@ #define USER_SPACE_BITS 39 #define VM_MAXUSER_ADDRESS ((1ULL << USER_SPACE_BITS) - 0x8000) #define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS (3ULL << (USER_SPACE_BITS - 2)) +#endif #define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xffffff8000000000ULL) #define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xffffff83ffffffffULL) diff --git a/sys/arch/mips64/include/vmparam.h b/sys/arch/mips64/include/vmparam.h index eef1c18f286..cfc8f55a05b 100644 --- a/sys/arch/mips64/include/vmparam.h +++ b/sys/arch/mips64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.29 2016/12/23 12:38:16 visa Exp $ */ +/* $OpenBSD: vmparam.h,v 1.30 2023/03/19 20:32:13 kettenis Exp $ */ /* $NetBSD: vmparam.h,v 1.5 1994/10/26 21:10:10 cgd Exp $ */ /* @@ -99,6 +99,9 @@ #define VM_MIN_ADDRESS ((vaddr_t)0x0000000000004000L) #define VM_MAXUSER_ADDRESS ((vaddr_t)0x0000010000000000L) #define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS ((vaddr_t)0x000000c000000000L) +#endif #define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0xc000000000000000L) #define VM_MAX_KERNEL_ADDRESS ((vaddr_t)0xc000000040000000L) diff --git a/sys/arch/powerpc64/include/vmparam.h b/sys/arch/powerpc64/include/vmparam.h index 56061429181..af8831a71ec 100644 --- a/sys/arch/powerpc64/include/vmparam.h +++ b/sys/arch/powerpc64/include/vmparam.h @@ -46,5 +46,8 @@ #define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) #define VM_MAXUSER_ADDRESS 0xbffffffffffff000UL #define VM_MAX_ADDRESS 0xffffffffffffffffUL +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS 0x9000000000000000UL +#endif #define VM_MIN_KERNEL_ADDRESS 0xc000000000000000UL #define VM_MAX_KERNEL_ADDRESS 0xc0000007ffffffffUL diff --git a/sys/arch/riscv64/include/vmparam.h b/sys/arch/riscv64/include/vmparam.h index c9e63887d63..fa1fd0b7461 100644 --- a/sys/arch/riscv64/include/vmparam.h +++ b/sys/arch/riscv64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.6 2022/03/22 06:47:38 miod Exp $ */ +/* $OpenBSD: vmparam.h,v 1.7 2023/03/19 20:32:13 kettenis Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -175,6 +175,9 @@ #define VM_MINUSER_ADDRESS (VM_MIN_USER_ADDRESS) // XXX OpenBSD/arm64 saves 8 * PAGE_SIZE at top of VM_MAXUSER_ADDRESS. Why? #define VM_MAXUSER_ADDRESS (VM_MAX_USER_ADDRESS) +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS (VM_MAXUSER_ADDRESS * 3 / 4) +#endif #define KERNBASE (VM_MIN_KERNEL_ADDRESS) diff --git a/sys/arch/sparc64/include/vmparam.h b/sys/arch/sparc64/include/vmparam.h index 42c9075482e..a7a4a4bd593 100644 --- a/sys/arch/sparc64/include/vmparam.h +++ b/sys/arch/sparc64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.33 2021/08/03 04:45:54 semarie Exp $ */ +/* $OpenBSD: vmparam.h,v 1.34 2023/03/19 20:32:13 kettenis Exp $ */ /* $NetBSD: vmparam.h,v 1.18 2001/05/01 02:19:19 thorpej Exp $ */ /* @@ -103,6 +103,9 @@ #define VM_MIN_ADDRESS ((vaddr_t)PAGE_SIZE) #define VM_MAX_ADDRESS ((vaddr_t)-1) #define VM_MAXUSER_ADDRESS ((vaddr_t)-PAGE_SIZE) +#ifdef _KERNEL +#define VM_MIN_STACK_ADDRESS ((vaddr_t)0xfffffe0000000000L) +#endif /* map PIE into the first quarter of the address space before hole */ #define VM_PIE_MIN_ADDR PAGE_SIZE diff --git a/sys/kern/exec_subr.c b/sys/kern/exec_subr.c index 5407a18cf66..a02566bf797 100644 --- a/sys/kern/exec_subr.c +++ b/sys/kern/exec_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_subr.c,v 1.65 2023/01/31 15:18:56 deraadt Exp $ */ +/* $OpenBSD: exec_subr.c,v 1.66 2023/03/19 20:32:13 kettenis Exp $ */ /* $NetBSD: exec_subr.c,v 1.9 1994/12/04 03:10:42 mycroft Exp $ */ /* @@ -383,7 +383,7 @@ vmcmd_randomize(struct proc *p, struct exec_vmcmd *cmd) int exec_setup_stack(struct proc *p, struct exec_package *epp) { - vaddr_t sgap; + vsize_t dist = 0; #ifdef MACHINE_STACK_GROWS_UP epp->ep_maxsaddr = USRSTACK; @@ -394,18 +394,26 @@ exec_setup_stack(struct proc *p, struct exec_package *epp) #endif epp->ep_ssize = round_page(lim_cur(RLIMIT_STACK)); +#ifdef VM_MIN_STACK_ADDRESS + dist = USRSTACK - MAXSSIZ - MAXSSIZ_GUARD - VM_MIN_STACK_ADDRESS; + if (dist >> PAGE_SHIFT > 0xffffffff) + dist = (vsize_t)arc4random() << PAGE_SHIFT; + else + dist = (vsize_t)arc4random_uniform(dist >> PAGE_SHIFT) << PAGE_SHIFT; +#else if (stackgap_random != 0) { - sgap = arc4random() & (stackgap_random - 1); - sgap = trunc_page(sgap); + dist = arc4random() & (stackgap_random - 1); + dist = trunc_page(dist); + } +#endif #ifdef MACHINE_STACK_GROWS_UP - epp->ep_maxsaddr += sgap; - epp->ep_minsaddr += sgap; + epp->ep_maxsaddr += dist; + epp->ep_minsaddr += dist; #else - epp->ep_maxsaddr -= sgap; - epp->ep_minsaddr -= sgap; + epp->ep_maxsaddr -= dist; + epp->ep_minsaddr -= dist; #endif - } /* * set up commands for stack. note that this takes *two*, one to -- 2.20.1