summaryrefslogtreecommitdiffstats
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
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
-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