summaryrefslogtreecommitdiff
path: root/sys/uvm
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2015-03-30 21:08:41 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2015-03-30 21:08:41 +0000
commitcbcb22b06c8a154b39499941e4bf5b9d6e0ab756 (patch)
tree6067bc0259d8df037242675f31f741069aa8d408 /sys/uvm
parent2144a111bea8a88f1cc4c1922c3503207fbf565d (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.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
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);