Add new uvm function called uvm_map_pie() which takes align as a
authorkurt <kurt@openbsd.org>
Fri, 18 Jul 2008 16:40:17 +0000 (16:40 +0000)
committerkurt <kurt@openbsd.org>
Fri, 18 Jul 2008 16:40:17 +0000 (16:40 +0000)
parameter and returns an aligned random load address for position
independent executables to use. This also adds three new vmparam.h
defines to specify the maximum address, minimum address and minimum
allowed alignment for uvm_map_pie() to use. The PIE address range
for i386 was carefully selected to work well within the i386 W^X
framework.

With much help and feedback from weingart@.
okay weingart@, miod@, kettenis@, drahn@

sys/arch/amd64/include/vmparam.h
sys/arch/i386/include/vmparam.h
sys/arch/macppc/include/vmparam.h
sys/arch/sparc64/include/vmparam.h
sys/uvm/uvm_map.c
sys/uvm/uvm_map.h

index 3822f13..fd82b22 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmparam.h,v 1.9 2008/06/24 21:24:03 deraadt Exp $     */
+/*     $OpenBSD: vmparam.h,v 1.10 2008/07/18 16:40:17 kurt Exp $       */
 /*     $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */
 
 /*-
 
 #define VM_MAXUSER_ADDRESS32   0xffffc000
 
+/* map PIE into approximately the first quarter of user va space */
+#define VM_PIE_MIN_ADDR                VM_MIN_ADDRESS
+#define VM_PIE_MAX_ADDR                0x200000000000
+
 /* virtual sizes (bytes) for various kernel submaps */
 #define VM_PHYS_SIZE           (USRIOSIZE*PAGE_SIZE)
 
index e871997..9c2163e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmparam.h,v 1.40 2008/06/24 21:24:03 deraadt Exp $    */
+/*     $OpenBSD: vmparam.h,v 1.41 2008/07/18 16:40:17 kurt Exp $       */
 /*     $NetBSD: vmparam.h,v 1.15 1994/10/27 04:16:34 cgd Exp $ */
 
 /*-
 /* I386 has a line where all code is executable: 0 - I386_MAX_EXE_ADDR */
 #define I386_MAX_EXE_ADDR 0x20000000           /* exec line */
 
+/* map PIE into 320MB - 448MB address range */
+#define VM_PIE_MIN_ADDR 0x14000000
+#define VM_PIE_MAX_ADDR 0x1C000000
+
 /*
  * Size of shared memory map
  */
index ab20ab9..c0fcbd2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmparam.h,v 1.19 2007/06/14 14:27:46 drahn Exp $      */
+/*     $OpenBSD: vmparam.h,v 1.20 2008/07/18 16:40:17 kurt Exp $       */
 /*     $NetBSD: vmparam.h,v 1.1 1996/09/30 16:34:38 ws Exp $   */
 
 /*-
 #define        VM_MAX_ADDRESS          VM_MAXUSER_ADDRESS
 #define        VM_MIN_KERNEL_ADDRESS   ((vaddr_t)(PPC_KERNEL_SR << ADDR_SR_SHIFT))
 
+/* map PIE into approximately the first quarter of user va space */
+#define VM_PIE_MIN_ADDR                PAGE_SIZE
+#define VM_PIE_MAX_ADDR                0x40000000
+
 /* ppc_kvm_stolen is so that vm space can be stolen before vm is fully
  * initialized.
  */
index ba1bdaf..f223969 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmparam.h,v 1.17 2008/06/04 18:11:34 miod Exp $       */
+/*     $OpenBSD: vmparam.h,v 1.18 2008/07/18 16:40:17 kurt Exp $       */
 /*     $NetBSD: vmparam.h,v 1.18 2001/05/01 02:19:19 thorpej Exp $ */
 
 /*
 #define VM_MAX_ADDRESS         ((vaddr_t)-1)
 #define VM_MAXUSER_ADDRESS     ((vaddr_t)-1)
 
+/* map PIE into the first quarter of the address space before hole */
+#define VM_PIE_MIN_ADDR                PAGE_SIZE
+#define VM_PIE_MAX_ADDR                0x10000000000
+
 #define VM_MIN_KERNEL_ADDRESS  ((vaddr_t)KERNBASE)
 #define VM_MAX_KERNEL_ADDRESS  ((vaddr_t)0x000007ffffffffffL)
 
index a13a7ce..338ec1f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_map.c,v 1.100 2008/06/09 20:30:23 miod Exp $      */
+/*     $OpenBSD: uvm_map.c,v 1.101 2008/07/18 16:40:17 kurt Exp $      */
 /*     $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */
 
 /* 
@@ -1099,6 +1099,45 @@ uvm_map_spacefits(struct vm_map *map, vaddr_t *phint, vsize_t length,
        return (TRUE);
 }
 
+/*
+ * uvm_map_pie: return a random load address for a PIE executable
+ * properly aligned.
+ */
+
+#ifndef VM_PIE_MAX_ADDR
+#define VM_PIE_MAX_ADDR (VM_MAXUSER_ADDRESS / 4)
+#endif
+
+#ifndef VM_PIE_MIN_ADDR
+#define VM_PIE_MIN_ADDR VM_MIN_ADDRESS
+#endif
+
+#ifndef VM_PIE_MIN_ALIGN
+#define VM_PIE_MIN_ALIGN PAGE_SIZE
+#endif
+
+vaddr_t
+uvm_map_pie(vaddr_t align)
+{
+       vaddr_t addr, space, min;
+
+       align = MAX(align, VM_PIE_MIN_ALIGN);
+
+       /* round up to next alignment */
+       min = (VM_PIE_MIN_ADDR + align - 1) & ~(align - 1);
+
+       if (align >= VM_PIE_MAX_ADDR || min >= VM_PIE_MAX_ADDR)
+               return (align);
+
+       space = (VM_PIE_MAX_ADDR - min) / align;
+       space = MIN(space, (u_int32_t)-1);
+
+       addr = (vaddr_t)arc4random_uniform((u_int32_t)space) * align;
+       addr += min;
+
+       return (addr);
+}
+
 /*
  * uvm_map_hint: return the beginning of the best area suitable for
  * creating a new mapping with "prot" protection.
index 5ed91a7..456f9a5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_map.h,v 1.38 2007/04/11 12:10:42 art Exp $        */
+/*     $OpenBSD: uvm_map.h,v 1.39 2008/07/18 16:40:17 kurt Exp $       */
 /*     $NetBSD: uvm_map.h,v 1.24 2001/02/18 21:19:08 chs Exp $ */
 
 /* 
@@ -294,6 +294,7 @@ int         uvm_map_extract(vm_map_t, vaddr_t, vsize_t,
                        vm_map_t, vaddr_t *, int);
 vm_map_entry_t uvm_map_findspace(vm_map_t, vaddr_t, vsize_t, vaddr_t *,
                        struct uvm_object *, voff_t, vsize_t, int);
+vaddr_t                uvm_map_pie(vaddr_t);
 vaddr_t                uvm_map_hint(struct proc *, vm_prot_t);
 int            uvm_map_inherit(vm_map_t, vaddr_t, vaddr_t, vm_inherit_t);
 int            uvm_map_advice(vm_map_t, vaddr_t, vaddr_t, int);