diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2015-03-30 21:08:41 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2015-03-30 21:08:41 +0000 |
commit | cbcb22b06c8a154b39499941e4bf5b9d6e0ab756 (patch) | |
tree | 6067bc0259d8df037242675f31f741069aa8d408 /sys/uvm | |
parent | 2144a111bea8a88f1cc4c1922c3503207fbf565d (diff) |
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.
Diffstat (limited to 'sys/uvm')
-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 |
4 files changed, 22 insertions, 12 deletions
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); |