mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-22 15:47:37 +00:00
Do not drop vm_map lock between doing vm_map_remove() and vm_map_insert().
For this, introduce vm_map_fixed() that does that for MAP_FIXED case. Dropping the lock allowed for parallel thread to occupy the freed space. Reported by: Tijl Coosemans <tijl ulyssis org> Reviewed by: alc Approved by: re (kensmith) MFC after: 2 weeks
This commit is contained in:
parent
5114048b63
commit
d239bd3ccc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=171902
@ -155,6 +155,22 @@ static void vmspace_zdtor(void *mem, int size, void *arg);
|
|||||||
#define PROC_VMSPACE_LOCK(p) do { } while (0)
|
#define PROC_VMSPACE_LOCK(p) do { } while (0)
|
||||||
#define PROC_VMSPACE_UNLOCK(p) do { } while (0)
|
#define PROC_VMSPACE_UNLOCK(p) do { } while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VM_MAP_RANGE_CHECK: [ internal use only ]
|
||||||
|
*
|
||||||
|
* Asserts that the starting and ending region
|
||||||
|
* addresses fall within the valid range of the map.
|
||||||
|
*/
|
||||||
|
#define VM_MAP_RANGE_CHECK(map, start, end) \
|
||||||
|
{ \
|
||||||
|
if (start < vm_map_min(map)) \
|
||||||
|
start = vm_map_min(map); \
|
||||||
|
if (end > vm_map_max(map)) \
|
||||||
|
end = vm_map_max(map); \
|
||||||
|
if (start > end) \
|
||||||
|
start = end; \
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vm_map_startup(void)
|
vm_map_startup(void)
|
||||||
{
|
{
|
||||||
@ -1145,6 +1161,25 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
|
||||||
|
vm_offset_t *addr /* IN/OUT */, vm_size_t length, vm_prot_t prot,
|
||||||
|
vm_prot_t max, int cow)
|
||||||
|
{
|
||||||
|
vm_offset_t start, end;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
start = *addr;
|
||||||
|
vm_map_lock(map);
|
||||||
|
end = start + length;
|
||||||
|
VM_MAP_RANGE_CHECK(map, start, end);
|
||||||
|
(void) vm_map_delete(map, start, end);
|
||||||
|
result = vm_map_insert(map, object, offset, start, end, prot,
|
||||||
|
max, cow);
|
||||||
|
vm_map_unlock(map);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vm_map_find finds an unallocated region in the target address
|
* vm_map_find finds an unallocated region in the target address
|
||||||
* map with the given length. The search is defined to be
|
* map with the given length. The search is defined to be
|
||||||
@ -1354,22 +1389,6 @@ _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* VM_MAP_RANGE_CHECK: [ internal use only ]
|
|
||||||
*
|
|
||||||
* Asserts that the starting and ending region
|
|
||||||
* addresses fall within the valid range of the map.
|
|
||||||
*/
|
|
||||||
#define VM_MAP_RANGE_CHECK(map, start, end) \
|
|
||||||
{ \
|
|
||||||
if (start < vm_map_min(map)) \
|
|
||||||
start = vm_map_min(map); \
|
|
||||||
if (end > vm_map_max(map)) \
|
|
||||||
end = vm_map_max(map); \
|
|
||||||
if (start > end) \
|
|
||||||
start = end; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vm_map_submap: [ kernel use only ]
|
* vm_map_submap: [ kernel use only ]
|
||||||
*
|
*
|
||||||
|
@ -333,6 +333,7 @@ boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t
|
|||||||
vm_map_t vm_map_create(pmap_t, vm_offset_t, vm_offset_t);
|
vm_map_t vm_map_create(pmap_t, vm_offset_t, vm_offset_t);
|
||||||
int vm_map_delete (vm_map_t, vm_offset_t, vm_offset_t);
|
int vm_map_delete (vm_map_t, vm_offset_t, vm_offset_t);
|
||||||
int vm_map_find (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, boolean_t, vm_prot_t, vm_prot_t, int);
|
int vm_map_find (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, boolean_t, vm_prot_t, vm_prot_t, int);
|
||||||
|
int vm_map_fixed (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int);
|
||||||
int vm_map_findspace (vm_map_t, vm_offset_t, vm_size_t, vm_offset_t *);
|
int vm_map_findspace (vm_map_t, vm_offset_t, vm_size_t, vm_offset_t *);
|
||||||
int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t);
|
int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t);
|
||||||
void vm_map_init (struct vm_map *, vm_offset_t, vm_offset_t);
|
void vm_map_init (struct vm_map *, vm_offset_t, vm_offset_t);
|
||||||
|
@ -1341,7 +1341,6 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
|||||||
if (*addr != trunc_page(*addr))
|
if (*addr != trunc_page(*addr))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
fitit = FALSE;
|
fitit = FALSE;
|
||||||
(void) vm_map_remove(map, *addr, *addr + size);
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Lookup/allocate object.
|
* Lookup/allocate object.
|
||||||
@ -1400,8 +1399,11 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
|||||||
if (flags & MAP_STACK)
|
if (flags & MAP_STACK)
|
||||||
rv = vm_map_stack(map, *addr, size, prot, maxprot,
|
rv = vm_map_stack(map, *addr, size, prot, maxprot,
|
||||||
docow | MAP_STACK_GROWS_DOWN);
|
docow | MAP_STACK_GROWS_DOWN);
|
||||||
|
else if (fitit)
|
||||||
|
rv = vm_map_find(map, object, foff, addr, size, TRUE,
|
||||||
|
prot, maxprot, docow);
|
||||||
else
|
else
|
||||||
rv = vm_map_find(map, object, foff, addr, size, fitit,
|
rv = vm_map_fixed(map, object, foff, addr, size,
|
||||||
prot, maxprot, docow);
|
prot, maxprot, docow);
|
||||||
|
|
||||||
if (rv != KERN_SUCCESS) {
|
if (rv != KERN_SUCCESS) {
|
||||||
|
Loading…
Reference in New Issue
Block a user