From c62276a4f36e19bbf603756107d0f12ed6ad2909 Mon Sep 17 00:00:00 2001 From: kurt Date: Fri, 18 Jul 2008 16:40:17 +0000 Subject: [PATCH] Add new uvm function called uvm_map_pie() which takes align as a 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 | 6 ++++- sys/arch/i386/include/vmparam.h | 6 ++++- sys/arch/macppc/include/vmparam.h | 6 ++++- sys/arch/sparc64/include/vmparam.h | 6 ++++- sys/uvm/uvm_map.c | 41 +++++++++++++++++++++++++++++- sys/uvm/uvm_map.h | 3 ++- 6 files changed, 62 insertions(+), 6 deletions(-) diff --git a/sys/arch/amd64/include/vmparam.h b/sys/arch/amd64/include/vmparam.h index 3822f13d557..fd82b226db2 100644 --- a/sys/arch/amd64/include/vmparam.h +++ b/sys/arch/amd64/include/vmparam.h @@ -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 $ */ /*- @@ -96,6 +96,10 @@ #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) diff --git a/sys/arch/i386/include/vmparam.h b/sys/arch/i386/include/vmparam.h index e871997fd43..9c2163e6c2d 100644 --- a/sys/arch/i386/include/vmparam.h +++ b/sys/arch/i386/include/vmparam.h @@ -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 $ */ /*- @@ -77,6 +77,10 @@ /* 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 */ diff --git a/sys/arch/macppc/include/vmparam.h b/sys/arch/macppc/include/vmparam.h index ab20ab911a9..c0fcbd26b80 100644 --- a/sys/arch/macppc/include/vmparam.h +++ b/sys/arch/macppc/include/vmparam.h @@ -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 $ */ /*- @@ -80,6 +80,10 @@ #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. */ diff --git a/sys/arch/sparc64/include/vmparam.h b/sys/arch/sparc64/include/vmparam.h index ba1bdaf2120..f2239697466 100644 --- a/sys/arch/sparc64/include/vmparam.h +++ b/sys/arch/sparc64/include/vmparam.h @@ -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 $ */ /* @@ -131,6 +131,10 @@ #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) diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c index a13a7ce92a6..338ec1fc99e 100644 --- a/sys/uvm/uvm_map.c +++ b/sys/uvm/uvm_map.c @@ -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. diff --git a/sys/uvm/uvm_map.h b/sys/uvm/uvm_map.h index 5ed91a71a72..456f9a5e516 100644 --- a/sys/uvm/uvm_map.h +++ b/sys/uvm/uvm_map.h @@ -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); -- 2.20.1