- The Open Group Base Specifications Issue 6 specifies that an munmap(2)
must return EINVAL if size is zero. Submitted by: tegge - In order to avoid a race condition in multithreaded applications, the check and removal operations by munmap(2) must be in the same critical section. To accomodate this, vm_map_check_protection() is modified to require its caller to obtain at least a read lock on the map.
This commit is contained in:
parent
8f101a2f31
commit
d88346020b
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user