summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2015-03-30 21:08:38 +0000
committermiod <miod@openbsd.org>2015-03-30 21:08:38 +0000
commite0e97bfb581cc08b703af3bb2b3e0efa5f5910fe (patch)
tree0950fad276c251ea79d722d0f06ab154f898be54
parent#if 0 various unused definitions. (diff)
downloadwireguard-openbsd-e0e97bfb581cc08b703af3bb2b3e0efa5f5910fe.tar.xz
wireguard-openbsd-e0e97bfb581cc08b703af3bb2b3e0efa5f5910fe.zip
Extend uvm_map_hint() to get an address range as extra arguments, and make
sure it will return an address within that range. Use this in uaddr_rnd_select() to make sure we will not attempt to pick an address beyond what we are allowed to map. In my trees for 9 months, blackmailed s2k15 attendees into agreeing now would be a good time to commit.
-rw-r--r--sys/kern/exec_elf.c5
-rw-r--r--sys/uvm/uvm_addr.c16
-rw-r--r--sys/uvm/uvm_map.c9
-rw-r--r--sys/uvm/uvm_map.h4
-rw-r--r--sys/uvm/uvm_mmap.c5
5 files changed, 25 insertions, 14 deletions
diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c
index 50a52badb42..5ceea1f7303 100644
--- a/sys/kern/exec_elf.c
+++ b/sys/kern/exec_elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.c,v 1.112 2015/02/10 23:39:57 guenther Exp $ */
+/* $OpenBSD: exec_elf.c,v 1.113 2015/03/30 21:08:38 miod Exp $ */
/*
* Copyright (c) 1996 Per Fogelstrom
@@ -377,7 +377,8 @@ ELFNAME(load_file)(struct proc *p, char *path, struct exec_package *epp,
* would (i.e. something safely out of the way).
*/
if (pos == ELFDEFNNAME(NO_ADDR)) {
- pos = uvm_map_hint(p->p_vmspace, PROT_EXEC);
+ pos = uvm_map_hint(p->p_vmspace, PROT_EXEC,
+ VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
}
pos = ELF_ROUND(pos, file_align);
diff --git a/sys/uvm/uvm_addr.c b/sys/uvm/uvm_addr.c
index e3f39b32105..5b153ed5ba0 100644
--- a/sys/uvm/uvm_addr.c
+++ b/sys/uvm/uvm_addr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_addr.c,v 1.12 2015/03/30 21:05:17 miod Exp $ */
+/* $OpenBSD: uvm_addr.c,v 1.13 2015/03/30 21:08:40 miod Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -564,6 +564,7 @@ uaddr_rnd_select(struct vm_map *map, struct uvm_addr_state *uaddr,
vm_prot_t prot, vaddr_t hint)
{
struct vmspace *vm;
+ vaddr_t minaddr, maxaddr;
vaddr_t guard_sz;
vaddr_t low_addr, high_addr;
struct vm_map_entry *entry, *next;
@@ -576,22 +577,25 @@ uaddr_rnd_select(struct vm_map *map, struct uvm_addr_state *uaddr,
/* Deal with guardpages: search for space with one extra page. */
guard_sz = ((map->flags & VM_MAP_GUARDPAGES) == 0 ? 0 : PAGE_SIZE);
+ minaddr = uvm_addr_align_forward(uaddr->uaddr_minaddr, align, offset);
+ maxaddr = uvm_addr_align_backward(uaddr->uaddr_maxaddr - sz - guard_sz,
+ align, offset);
+
/* Quick fail if the allocation won't fit. */
- if (uaddr->uaddr_maxaddr - uaddr->uaddr_minaddr < sz + guard_sz)
+ if (minaddr >= maxaddr)
return ENOMEM;
/* Select a hint. */
if (hint == 0)
- hint = uvm_map_hint(vm, prot);
+ hint = uvm_map_hint(vm, prot, minaddr, maxaddr);
/* Clamp hint to uaddr range. */
- hint = MIN(MAX(hint, uaddr->uaddr_minaddr),
- uaddr->uaddr_maxaddr - sz - guard_sz);
+ hint = MIN(MAX(hint, minaddr), maxaddr);
/* Align hint to align,offset parameters. */
tmp = hint;
hint = uvm_addr_align_forward(tmp, align, offset);
/* Check for overflow during alignment. */
- if (hint < tmp || hint > uaddr->uaddr_maxaddr - sz - guard_sz)
+ if (hint < tmp || hint > maxaddr)
return ENOMEM; /* Compatibility mode: never look backwards. */
before_gap = 0;
diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c
index 2323189738f..80bfee3bb13 100644
--- a/sys/uvm/uvm_map.c
+++ b/sys/uvm/uvm_map.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_map.c,v 1.188 2015/03/14 03:38:53 jsg Exp $ */
+/* $OpenBSD: uvm_map.c,v 1.189 2015/03/30 21:08:40 miod Exp $ */
/* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */
/*
@@ -3713,7 +3713,8 @@ uvmspace_fork(struct process *pr)
* creating a new mapping with "prot" protection.
*/
vaddr_t
-uvm_map_hint(struct vmspace *vm, vm_prot_t prot)
+uvm_map_hint(struct vmspace *vm, vm_prot_t prot, vaddr_t minaddr,
+ vaddr_t maxaddr)
{
vaddr_t addr;
vaddr_t spacing;
@@ -3746,6 +3747,10 @@ uvm_map_hint(struct vmspace *vm, vm_prot_t prot)
if (vm->vm_dused < spacing >> PAGE_SHIFT)
addr += BRKSIZ;
#if !defined(__vax__)
+ if (addr < maxaddr) {
+ while (spacing > maxaddr - addr)
+ spacing >>= 1;
+ }
addr += arc4random() & spacing;
#endif
return (round_page(addr));
diff --git a/sys/uvm/uvm_map.h b/sys/uvm/uvm_map.h
index df132b17459..c23e070f703 100644
--- a/sys/uvm/uvm_map.h
+++ b/sys/uvm/uvm_map.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_map.h,v 1.53 2015/02/06 09:04:34 tedu Exp $ */
+/* $OpenBSD: uvm_map.h,v 1.54 2015/03/30 21:08:40 miod Exp $ */
/* $NetBSD: uvm_map.h,v 1.24 2001/02/18 21:19:08 chs Exp $ */
/*
@@ -384,7 +384,7 @@ vm_map_t uvm_map_create(pmap_t, vaddr_t, vaddr_t, int);
int uvm_map_extract(struct vm_map*, vaddr_t, vsize_t, vaddr_t*,
int);
vaddr_t uvm_map_pie(vaddr_t);
-vaddr_t uvm_map_hint(struct vmspace *, vm_prot_t);
+vaddr_t uvm_map_hint(struct vmspace *, vm_prot_t, vaddr_t, vaddr_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);
void uvm_map_init(void);
diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c
index b2d749cfb54..9f4205c8d51 100644
--- a/sys/uvm/uvm_mmap.c
+++ b/sys/uvm/uvm_mmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_mmap.c,v 1.107 2015/02/13 13:35:03 millert Exp $ */
+/* $OpenBSD: uvm_mmap.c,v 1.108 2015/03/30 21:08:40 miod Exp $ */
/* $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $ */
/*
@@ -152,7 +152,8 @@ sys_mquery(struct proc *p, void *v, register_t *retval)
}
if (vaddr == 0)
- vaddr = uvm_map_hint(p->p_vmspace, prot);
+ vaddr = uvm_map_hint(p->p_vmspace, prot, VM_MIN_ADDRESS,
+ VM_MAXUSER_ADDRESS);
error = uvm_map_mquery(&p->p_vmspace->vm_map, &vaddr, size, uoff,
flags);