summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-07-30 14:13:57 +0000
committerkib <kib@FreeBSD.org>2011-07-30 14:13:57 +0000
commit645f499b5d3641bac9a4abe3b0e295baac6d3de6 (patch)
tree11e7298569d761c6de538384fb3f0205e6faf5be /sys/vm
parent2c49d0ddddb36a82316ce90920948d8b660a8da4 (diff)
downloadFreeBSD-src-645f499b5d3641bac9a4abe3b0e295baac6d3de6.zip
FreeBSD-src-645f499b5d3641bac9a4abe3b0e295baac6d3de6.tar.gz
Fix a race in the device pager allocation. If another thread won and
allocated the device pager for the given handle, then the object fictitious pages list and the object membership in the global object list still need to be initialized. Otherwise, dev_pager_dealloc() will traverse uninitialized pointers. Reported and tested by: pho Reviewed by: jhb Approved by: re (kensmith) MFC after: 1 week
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/device_pager.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 411482a..d46d170 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -147,6 +147,7 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
object1 = vm_object_allocate(OBJT_DEVICE, pindex);
object1->flags |= OBJ_COLORED;
object1->pg_color = atop(paddr) - OFF_TO_IDX(off - PAGE_SIZE);
+ TAILQ_INIT(&object1->un_pager.devp.devp_pglist);
mtx_lock(&dev_pager_mtx);
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
if (object != NULL) {
@@ -159,7 +160,6 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
object = object1;
object1 = NULL;
object->handle = handle;
- TAILQ_INIT(&object->un_pager.devp.devp_pglist);
TAILQ_INSERT_TAIL(&dev_pager_object_list, object,
pager_object_list);
}
@@ -169,7 +169,14 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
}
mtx_unlock(&dev_pager_mtx);
dev_relthread(dev, ref);
- vm_object_deallocate(object1);
+ if (object1 != NULL) {
+ object1->handle = object1;
+ mtx_lock(&dev_pager_mtx);
+ TAILQ_INSERT_TAIL(&dev_pager_object_list, object1,
+ pager_object_list);
+ mtx_unlock(&dev_pager_mtx);
+ vm_object_deallocate(object1);
+ }
return (object);
}
OpenPOWER on IntegriCloud