diff options
author | 2015-03-30 21:08:38 +0000 | |
---|---|---|
committer | 2015-03-30 21:08:38 +0000 | |
commit | e0e97bfb581cc08b703af3bb2b3e0efa5f5910fe (patch) | |
tree | 0950fad276c251ea79d722d0f06ab154f898be54 | |
parent | #if 0 various unused definitions. (diff) | |
download | wireguard-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.c | 5 | ||||
-rw-r--r-- | sys/uvm/uvm_addr.c | 16 | ||||
-rw-r--r-- | sys/uvm/uvm_map.c | 9 | ||||
-rw-r--r-- | sys/uvm/uvm_map.h | 4 | ||||
-rw-r--r-- | sys/uvm/uvm_mmap.c | 5 |
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); |