aboutsummaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorJosef Bacik2017-04-28 09:49:19 -0400
committerJens Axboe2017-04-28 08:04:01 -0600
commit60ae36ad0340b1ba88530d6a5e141455dd3afd81 (patch)
tree53c39316d3556a156734ef78ab5300874ff53d6a /drivers/block
parentbf290f8f98b1a22fe131fa517ef66efb846cf849 (diff)
nbd: fix use after free on module unload
list_for_each_entry() isn't super safe if we're freeing the objects while we traverse the list. Also don't bother taking the extra reference, the module refcounting stuff will save us from having anybody messing with the device while we're trying to unload. Reported-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/nbd.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 5583dc4ff941..ac376b9b852d 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -2090,7 +2090,6 @@ static int nbd_exit_cb(int id, void *ptr, void *data)
struct list_head *list = (struct list_head *)data;
struct nbd_device *nbd = ptr;
- refcount_inc(&nbd->refs);
list_add_tail(&nbd->list, list);
return 0;
}
@@ -2106,11 +2105,12 @@ static void __exit nbd_cleanup(void)
idr_for_each(&nbd_index_idr, &nbd_exit_cb, &del_list);
mutex_unlock(&nbd_index_mutex);
- list_for_each_entry(nbd, &del_list, list) {
- if (refcount_read(&nbd->refs) != 2)
+ while (!list_empty(&del_list)) {
+ nbd = list_first_entry(&del_list, struct nbd_device, list);
+ list_del_init(&nbd->list);
+ if (refcount_read(&nbd->refs) != 1)
printk(KERN_ERR "nbd: possibly leaking a device\n");
nbd_put(nbd);
- nbd_put(nbd);
}
idr_destroy(&nbd_index_idr);