From 911e30e25724984efec56accba87f739cfca2937 Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Thu, 25 Nov 2010 08:18:15 +0000 Subject: [PATCH] mmap - add mmap offset randomization * mmap offset randomization, based upon OpenBSD's implementation in sys/uvm/uvm_map.c and sys/uvm/uvm_mmap.c. * The randomization is controllable via the sysctl vm.randomize_mmap, which by default is 0 (off). Obtained-from: OpenBSD --- sys/vm/vm_map.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ sys/vm/vm_map.h | 1 + sys/vm/vm_mmap.c | 10 +++------ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index b1fe76d7c6..79c1a02d42 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -99,6 +99,8 @@ #include #include +#include +#include /* * Virtual memory maps provide for the mapping, protection, and sharing @@ -150,6 +152,10 @@ static struct vm_map_entry map_entry_init[MAX_MAPENT]; static struct vm_map_entry cpu_map_entry_init[MAXCPU][VMEPERCPU]; static struct vm_map map_init[MAX_KMAP]; +static int randomize_mmap; +SYSCTL_INT(_vm, OID_AUTO, randomize_mmap, CTLFLAG_RW, &randomize_mmap, 0, + "Randomize mmap offsets"); + static void vm_map_entry_shadow(vm_map_entry_t entry); static vm_map_entry_t vm_map_entry_create(vm_map_t map, int *); static void vm_map_entry_dispose (vm_map_t map, vm_map_entry_t entry, int *); @@ -3482,6 +3488,56 @@ vmspace_unshare(struct proc *p) lwkt_reltoken(&vmspace_token); } +/* + * vm_map_hint: return the beginning of the best area suitable for + * creating a new mapping with "prot" protection. + * + * No requirements. + */ +vm_offset_t +vm_map_hint(struct proc *p, vm_offset_t addr, vm_prot_t prot) +{ + struct vmspace *vms = p->p_vmspace; + + if (!randomize_mmap) { + /* + * Set a reasonable start point for the hint if it was + * not specified or if it falls within the heap space. + * Hinted mmap()s do not allocate out of the heap space. + */ + if (addr == 0 || + (addr >= round_page((vm_offset_t)vms->vm_taddr) && + addr < round_page((vm_offset_t)vms->vm_daddr + maxdsiz))) { + addr = round_page((vm_offset_t)vms->vm_daddr + maxdsiz); + } + + return addr; + } + + if (addr != 0 && addr >= (vm_offset_t)vms->vm_daddr) + return addr; + +#ifdef notyet +#ifdef __i386__ + /* + * If executable skip first two pages, otherwise start + * after data + heap region. + */ + if ((prot & VM_PROT_EXECUTE) && + ((vm_offset_t)vms->vm_daddr >= I386_MAX_EXE_ADDR)) { + addr = (PAGE_SIZE * 2) + + (karc4random() & (I386_MAX_EXE_ADDR / 2 - 1)); + return (round_page(addr)); + } +#endif /* __i386__ */ +#endif /* notyet */ + + addr = (vm_offset_t)vms->vm_daddr + MAXDSIZ; + addr += karc4random() & (MIN((256 * 1024 * 1024), MAXDSIZ) - 1); + + return (round_page(addr)); +} + /* * Finds the VM object, offset, and protection for a given virtual address * in the specified map, assuming a page fault of the type specified. diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 0fbcfe1705..3b67c66f96 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -501,6 +501,7 @@ int vm_map_find (vm_map_t, vm_object_t, vm_ooffset_t, int); int vm_map_findspace (vm_map_t, vm_offset_t, vm_size_t, vm_size_t, int, vm_offset_t *); +vm_offset_t vm_map_hint(struct proc *, vm_offset_t, vm_prot_t); int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t); void vm_map_init (struct vm_map *, vm_offset_t, vm_offset_t, pmap_t); int vm_map_insert (vm_map_t, int *, vm_object_t, vm_ooffset_t, diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 514cde38de..89651858e9 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -249,14 +249,10 @@ kern_mmap(struct vmspace *vms, caddr_t uaddr, size_t ulen, return (EINVAL); } else { /* - * Set a reasonable start point for the hint if it was - * not specified or if it falls within the heap space. - * Hinted mmap()s do not allocate out of the heap space. + * Get a hint of where to map. It also provides mmap offset + * randomization if enabled. */ - if (addr == 0 || - (addr >= round_page((vm_offset_t)vms->vm_taddr) && - addr < round_page((vm_offset_t)vms->vm_daddr + maxdsiz))) - addr = round_page((vm_offset_t)vms->vm_daddr + maxdsiz); + addr = vm_map_hint(p, addr, prot); } if (flags & MAP_ANON) { -- 2.41.0