diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 6e2872f65ebf..2dda5f8baf41 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -144,7 +144,9 @@ kernacc(addr, len, rw) prot = rw; saddr = trunc_page((vm_offset_t)addr); eaddr = round_page((vm_offset_t)addr + len); + vm_map_lock_read(kernel_map); rv = vm_map_check_protection(kernel_map, saddr, eaddr, prot); + vm_map_unlock_read(kernel_map); return (rv == TRUE); } @@ -174,8 +176,10 @@ useracc(addr, len, rw) (vm_offset_t)addr + len < (vm_offset_t)addr) { return (FALSE); } + vm_map_lock_read(map); rv = vm_map_check_protection(map, trunc_page((vm_offset_t)addr), round_page((vm_offset_t)addr + len), prot); + vm_map_unlock_read(map); return (rv == TRUE); } diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 0fb7fc1c7f1f..e2c4c8ea538f 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -2227,6 +2227,8 @@ vm_map_remove(vm_map_t map, vm_offset_t start, vm_offset_t end) * might be mapped into a larger address space. * * NOTE! This code is also called by munmap(). + * + * The map must be locked. A read lock is sufficient. */ boolean_t vm_map_check_protection(vm_map_t map, vm_offset_t start, vm_offset_t end, @@ -2235,37 +2237,27 @@ vm_map_check_protection(vm_map_t map, vm_offset_t start, vm_offset_t end, vm_map_entry_t entry; vm_map_entry_t tmp_entry; - vm_map_lock_read(map); - if (!vm_map_lookup_entry(map, start, &tmp_entry)) { - vm_map_unlock_read(map); + if (!vm_map_lookup_entry(map, start, &tmp_entry)) return (FALSE); - } entry = tmp_entry; while (start < end) { - if (entry == &map->header) { - vm_map_unlock_read(map); + if (entry == &map->header) return (FALSE); - } /* * No holes allowed! */ - if (start < entry->start) { - vm_map_unlock_read(map); + if (start < entry->start) return (FALSE); - } /* * Check protection associated with entry. */ - if ((entry->protection & protection) != protection) { - vm_map_unlock_read(map); + if ((entry->protection & protection) != protection) return (FALSE); - } /* go to next entry */ start = entry->end; entry = entry->next; } - vm_map_unlock_read(map); return (TRUE); } diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 95e335aa7009..9025c4692e58 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -585,6 +585,8 @@ munmap(td, uap) addr = (vm_offset_t) uap->addr; size = uap->len; + if (size == 0) + return (EINVAL); pageoff = (addr & PAGE_MASK); addr -= pageoff; @@ -593,23 +595,23 @@ munmap(td, uap) if (addr + size < addr) return (EINVAL); - if (size == 0) - return (0); - /* * Check for illegal addresses. Watch out for address wrap... */ map = &td->td_proc->p_vmspace->vm_map; if (addr < vm_map_min(map) || addr + size > vm_map_max(map)) return (EINVAL); + vm_map_lock(map); /* * Make sure entire range is allocated. */ - if (!vm_map_check_protection(map, addr, addr + size, VM_PROT_NONE)) + if (!vm_map_check_protection(map, addr, addr + size, VM_PROT_NONE)) { + vm_map_unlock(map); return (EINVAL); - + } /* returns nothing but KERN_SUCCESS anyway */ - (void) vm_map_remove(map, addr, addr + size); + vm_map_delete(map, addr, addr + size); + vm_map_unlock(map); return (0); }