Aggressively randomize the location of the stack on all 64-bit architectures
authorkettenis <kettenis@openbsd.org>
Sun, 19 Mar 2023 20:32:13 +0000 (20:32 +0000)
committerkettenis <kettenis@openbsd.org>
Sun, 19 Mar 2023 20:32:13 +0000 (20:32 +0000)
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
sys/arch/arm64/include/vmparam.h
sys/arch/mips64/include/vmparam.h
sys/arch/powerpc64/include/vmparam.h
sys/arch/riscv64/include/vmparam.h
sys/arch/sparc64/include/vmparam.h
sys/kern/exec_subr.c

index fae0eee..d7b606a 100644 (file)
@@ -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
 
index 118fa0e..af4f674 100644 (file)
@@ -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)
 
index eef1c18..cfc8f55 100644 (file)
@@ -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)
 
index 5606142..af8831a 100644 (file)
@@ -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
index c9e6388..fa1fd0b 100644 (file)
@@ -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.
 #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)
 
index 42c9075..a7a4a4b 100644 (file)
@@ -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 $ */
 
 /*
 #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
index 5407a18..a02566b 100644 (file)
@@ -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