diff options
author | Ariane van der Steldt <ariane@cvs.openbsd.org> | 2011-05-29 15:18:20 +0000 |
---|---|---|
committer | Ariane van der Steldt <ariane@cvs.openbsd.org> | 2011-05-29 15:18:20 +0000 |
commit | 4ac0908a8d2e315886f644117c7660765bc13874 (patch) | |
tree | 3b5d1aeb811a0bcc288ae1adac3d510d758c01a7 | |
parent | 78e5e14fca94ad8e4b6911bd0296fad3a8ab1e2f (diff) |
Fix parameter range clamping in vmmap routines.
The old VM_MAP_RANGE_CHECK macro was wrong and caused code to be unreadable
(argument altering macros are harmful).
Each function now treats the memory range outside the map as it would treat
free memory: if it would error on being given free memory, it'll error
in a similar fashion when the start,end parameters fall outside the map.
If it would accept free memory in its argument range, it'll silently accept
the outside-map memory too.
Confirmed to help ports build machines.
-rw-r--r-- | sys/uvm/uvm_map.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c index ed9930f42f0..58406bd6efd 100644 --- a/sys/uvm/uvm_map.c +++ b/sys/uvm/uvm_map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_map.c,v 1.136 2011/05/24 15:27:36 ariane Exp $ */ +/* $OpenBSD: uvm_map.c,v 1.137 2011/05/29 15:18:19 ariane Exp $ */ /* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */ /* @@ -477,16 +477,6 @@ uvm_mapent_addr_remove(struct vm_map *map, struct vm_map_entry *entry) } /* - * Clamp start and end to map boundaries. - */ -#define VM_MAP_RANGE_CHECK(_map, _start, _end) \ - do { \ - (_start) = MAX((_start), vm_map_min((_map))); \ - (_end) = MIN((_end), vm_map_max((_map))); \ - (_start) = MIN((_start), (_end)); \ - } while (0) - -/* * uvm_map_reference: add reference to a map * * XXX check map reference counter lock @@ -1795,8 +1785,9 @@ uvm_unmap_remove(struct vm_map *map, vaddr_t start, vaddr_t end, { struct vm_map_entry *prev_hint, *next, *entry; - VM_MAP_RANGE_CHECK(map, start, end); - if (start == end) + start = MAX(start, map->min_offset); + end = MIN(end, map->max_offset); + if (start >= end) return; if ((map->flags & VM_MAP_INTRSAFE) == 0) @@ -2130,12 +2121,17 @@ uvm_map_pageable(struct vm_map *map, vaddr_t start, vaddr_t end, struct vm_map_entry *first, *last, *tmp; int error; + if (start > end) + return EINVAL; + if (start < map->min_offset) + return EFAULT; /* why? see first XXX below */ + if (end > map->max_offset) + return EINVAL; /* why? see second XXX below */ + KASSERT(map->flags & VM_MAP_PAGEABLE); if ((lockflags & UVM_LK_ENTER) == 0) vm_map_lock(map); - VM_MAP_RANGE_CHECK(map, start, end); - /* * Find first entry. * @@ -2917,8 +2913,11 @@ uvm_map_protect(struct vm_map *map, vaddr_t start, vaddr_t end, vm_prot_t mask; int error; - VM_MAP_RANGE_CHECK(map, start, end); - if (start == end) + if (start > end) + return EINVAL; + start = MAX(start, map->min_offset); + end = MIN(end, map->max_offset); + if (start >= end) return 0; error = 0; @@ -3685,9 +3684,11 @@ uvm_map_submap(struct vm_map *map, vaddr_t start, vaddr_t end, struct vm_map_entry *entry; int result; - vm_map_lock(map); + if (start > map->max_offset || end > map->max_offset || + start < map->min_offset || end < map->min_offset) + return EINVAL; - VM_MAP_RANGE_CHECK(map, start, end); + vm_map_lock(map); if (uvm_map_lookup_entry(map, start, &entry)) { UVM_MAP_CLIP_START(map, entry, start); @@ -3826,9 +3827,14 @@ uvm_map_inherit(struct vm_map *map, vaddr_t start, vaddr_t end, return (EINVAL); } - vm_map_lock(map); + if (start > end) + return EINVAL; + start = MAX(start, map->min_offset); + end = MIN(end, map->max_offset); + if (start >= end) + return 0; - VM_MAP_RANGE_CHECK(map, start, end); + vm_map_lock(map); entry = uvm_map_entrybyaddr(&map->addr, start); if (entry->end > start) @@ -3870,9 +3876,14 @@ uvm_map_advice(struct vm_map *map, vaddr_t start, vaddr_t end, int new_advice) return (EINVAL); } - vm_map_lock(map); + if (start > end) + return EINVAL; + start = MAX(start, map->min_offset); + end = MIN(end, map->max_offset); + if (start >= end) + return 0; - VM_MAP_RANGE_CHECK(map, start, end); + vm_map_lock(map); entry = uvm_map_entrybyaddr(&map->addr, start); if (entry != NULL && entry->end > start) @@ -4117,8 +4128,10 @@ uvm_map_clean(struct vm_map *map, vaddr_t start, vaddr_t end, int flags) KASSERT((flags & (PGO_FREE|PGO_DEACTIVATE)) != (PGO_FREE|PGO_DEACTIVATE)); + if (start > end || start < map->min_offset || end > map->max_offset) + return EINVAL; + vm_map_lock_read(map); - VM_MAP_RANGE_CHECK(map, start, end); first = uvm_map_entrybyaddr(&map->addr, start); /* |