Commit 9e60352c authored by Keith Busch's avatar Keith Busch Committed by Jens Axboe

NVMe: Do not open disks that are being deleted

It is possible the block layer will request to open a block device after
the driver deleted it. Subsequent releases will cause a double free,
or the disk's private_data is pointing to freed memory. This patch
protects the driver's freed disks from being opened and accessed: the
nvme namespaces are freed only when the device's refcount is 0, so at
that moment there were no active openers and no more should be allowed,
and it is safe to clear the disk's private_data that is about to be freed.
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Reported-by: default avatarHenry Chow <henry.chow@oracle.com>
Signed-off-by: default avatarMatthew Wilcox <matthew.r.wilcox@intel.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 5940c857
......@@ -1832,11 +1832,18 @@ static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode,
static int nvme_open(struct block_device *bdev, fmode_t mode)
{
struct nvme_ns *ns = bdev->bd_disk->private_data;
struct nvme_dev *dev = ns->dev;
int ret = 0;
struct nvme_ns *ns;
kref_get(&dev->kref);
return 0;
spin_lock(&dev_list_lock);
ns = bdev->bd_disk->private_data;
if (!ns)
ret = -ENXIO;
else if (!kref_get_unless_zero(&ns->dev->kref))
ret = -ENXIO;
spin_unlock(&dev_list_lock);
return ret;
}
static void nvme_free_dev(struct kref *kref);
......@@ -2711,6 +2718,11 @@ static void nvme_free_namespaces(struct nvme_dev *dev)
list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
list_del(&ns->list);
spin_lock(&dev_list_lock);
ns->disk->private_data = NULL;
spin_unlock(&dev_list_lock);
put_disk(ns->disk);
kfree(ns);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment