diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-08-16 12:54:41 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-09-14 14:45:05 +0200 |
commit | 22778b589af94261c2d8d0665220770d0b56d1a8 (patch) | |
tree | 97bdb1c058f030d30dfe0d566630010572a4fb35 /vm/vm_map.c | |
parent | 81747ac6d3e846d1955edaa94dee9065e541b7d8 (diff) |
vm: fix locking issues
Avoid accessing fields of `vm_object' objects without having it
locked. These problems have been found using a code transformation
done by Coccinelle that instrumented all accesses with a runtime
check, and manual inspection.
* vm/memory_object.c (memory_object_data_supply): Avoid accessing
fields without the lock.
* vm/vm_fault.c (vm_fault_page): Likewise.
* vm/vm_map.c (vm_map_submap): Properly lock `object'.
(vm_map_copy_overwrite): Avoid accessing fields without the lock.
(vm_map_copyin): Lock `src_object'.
* vm/vm_object.c (_vm_object_setup): Likewise.
(vm_object_allocate): Likewise.
(vm_object_terminate): Avoid accessing fields without the lock.
(vm_object_copy_slowly): Lock `new_object'.
(vm_object_copy_delayed): Lock `src_object' earlier, lock `new_copy'.
(vm_object_shadow): Lock `result'.
(vm_object_enter): Properly lock `object'. Avoid accessing fields
without the lock.
* vm/vm_pageout.c (vm_pageout_setup): Properly lock `old_object'.
Diffstat (limited to 'vm/vm_map.c')
-rw-r--r-- | vm/vm_map.c | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/vm/vm_map.c b/vm/vm_map.c index ae3ce21..9098dfd 100644 --- a/vm/vm_map.c +++ b/vm/vm_map.c @@ -1182,16 +1182,20 @@ kern_return_t vm_map_submap( if ((entry->vme_start == start) && (entry->vme_end == end) && (!entry->is_sub_map) && - ((object = entry->object.vm_object) == vm_submap_object) && - (object->resident_page_count == 0) && - (object->copy == VM_OBJECT_NULL) && - (object->shadow == VM_OBJECT_NULL) && - (!object->pager_created)) { - entry->object.vm_object = VM_OBJECT_NULL; - vm_object_deallocate(object); - entry->is_sub_map = TRUE; - vm_map_reference(entry->object.sub_map = submap); - result = KERN_SUCCESS; + ((object = entry->object.vm_object) == vm_submap_object)) { + vm_object_lock(object); + if ((object->resident_page_count == 0) && + (object->copy == VM_OBJECT_NULL) && + (object->shadow == VM_OBJECT_NULL) && + (!object->pager_created)) { + vm_object_unlock(object); + entry->object.vm_object = VM_OBJECT_NULL; + vm_object_deallocate(object); + entry->is_sub_map = TRUE; + vm_map_reference(entry->object.sub_map = submap); + result = KERN_SUCCESS; + } else + vm_object_unlock(object); } vm_map_unlock(map); @@ -2122,6 +2126,7 @@ start_pass_1: for (entry = tmp_entry;;) { vm_size_t sub_size = (entry->vme_end - entry->vme_start); vm_map_entry_t next = entry->vme_next; + vm_object_t object; if ( ! (entry->protection & VM_PROT_WRITE)) { vm_map_unlock(dst_map); @@ -2157,10 +2162,13 @@ start_pass_1: /* * Check for permanent objects in the destination. */ - - if ((entry->object.vm_object != VM_OBJECT_NULL) && - !entry->object.vm_object->temporary) - contains_permanent_objects = TRUE; + object = entry->object.vm_object; + if ((object != VM_OBJECT_NULL) + && ! contains_permanent_objects) { + vm_object_lock(object); + contains_permanent_objects = object->temporary; + vm_object_unlock(object); + } size -= sub_size; entry = next; @@ -2220,6 +2228,7 @@ start_pass_1: vm_map_entry_t copy_entry = vm_map_copy_first_entry(copy); vm_size_t copy_size = (copy_entry->vme_end - copy_entry->vme_start); vm_object_t object; + int temporary; entry = tmp_entry; size = (entry->vme_end - entry->vme_start); @@ -2275,8 +2284,15 @@ start_pass_1: */ object = entry->object.vm_object; + temporary = 0; + if (object != VM_OBJECT_NULL) { + vm_object_lock(object); + temporary = object->temporary; + vm_object_unlock(object); + } + if (!entry->is_shared && - ((object == VM_OBJECT_NULL) || object->temporary)) { + ((object == VM_OBJECT_NULL) || temporary)) { vm_object_t old_object = entry->object.vm_object; vm_offset_t old_offset = entry->offset; @@ -3219,11 +3235,15 @@ kern_return_t vm_map_copyin( /* * Attempt non-blocking copy-on-write optimizations. */ - + if (src_object) + vm_object_lock(src_object); if (src_destroy && (src_object == VM_OBJECT_NULL || (src_object->temporary && !src_object->use_shared_copy))) { + if (src_object) + vm_object_unlock(src_object); + /* * If we are destroying the source, and the object * is temporary, and not shared writable, @@ -3243,6 +3263,9 @@ kern_return_t vm_map_copyin( goto CopySuccessful; } + if (src_object) + vm_object_unlock(src_object); + if (!was_wired && vm_object_copy_temporary( &new_entry->object.vm_object, |