aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nvme-core.c
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2014-01-31 18:53:39 -0500
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2014-02-02 13:31:15 -0500
commit9ac27090f61ea6735a62b0a98c7669c833bcdc09 (patch)
tree1ac24bb79b089a52e162fa80b44d1a2ca0127051 /drivers/block/nvme-core.c
parentbdfd70fde389412be60f7e8aaed5732dc26fc8ac (diff)
NVMe: Namespace use after free on surprise removal
An nvme block device may have open references when the device is removed. New commands may still be sent on the removed device, so we need to ref count the opens, return errors for new commands, and not free the namespace and nvme_dev until all references are closed. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Diffstat (limited to 'drivers/block/nvme-core.c')
-rw-r--r--drivers/block/nvme-core.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 23728099e36f..cd39390710a0 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1716,10 +1716,31 @@ static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode,
1716#define nvme_compat_ioctl NULL 1716#define nvme_compat_ioctl NULL
1717#endif 1717#endif
1718 1718
1719static int nvme_open(struct block_device *bdev, fmode_t mode)
1720{
1721 struct nvme_ns *ns = bdev->bd_disk->private_data;
1722 struct nvme_dev *dev = ns->dev;
1723
1724 kref_get(&dev->kref);
1725 return 0;
1726}
1727
1728static void nvme_free_dev(struct kref *kref);
1729
1730static void nvme_release(struct gendisk *disk, fmode_t mode)
1731{
1732 struct nvme_ns *ns = disk->private_data;
1733 struct nvme_dev *dev = ns->dev;
1734
1735 kref_put(&dev->kref, nvme_free_dev);
1736}
1737
1719static const struct block_device_operations nvme_fops = { 1738static const struct block_device_operations nvme_fops = {
1720 .owner = THIS_MODULE, 1739 .owner = THIS_MODULE,
1721 .ioctl = nvme_ioctl, 1740 .ioctl = nvme_ioctl,
1722 .compat_ioctl = nvme_compat_ioctl, 1741 .compat_ioctl = nvme_compat_ioctl,
1742 .open = nvme_open,
1743 .release = nvme_release,
1723}; 1744};
1724 1745
1725static void nvme_resubmit_bios(struct nvme_queue *nvmeq) 1746static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
@@ -1849,13 +1870,6 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
1849 return NULL; 1870 return NULL;
1850} 1871}
1851 1872
1852static void nvme_ns_free(struct nvme_ns *ns)
1853{
1854 put_disk(ns->disk);
1855 blk_cleanup_queue(ns->queue);
1856 kfree(ns);
1857}
1858
1859static int set_queue_count(struct nvme_dev *dev, int count) 1873static int set_queue_count(struct nvme_dev *dev, int count)
1860{ 1874{
1861 int status; 1875 int status;
@@ -2287,12 +2301,13 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
2287 2301
2288static void nvme_dev_remove(struct nvme_dev *dev) 2302static void nvme_dev_remove(struct nvme_dev *dev)
2289{ 2303{
2290 struct nvme_ns *ns, *next; 2304 struct nvme_ns *ns;
2291 2305
2292 list_for_each_entry_safe(ns, next, &dev->namespaces, list) { 2306 list_for_each_entry(ns, &dev->namespaces, list) {
2293 list_del(&ns->list); 2307 if (ns->disk->flags & GENHD_FL_UP)
2294 del_gendisk(ns->disk); 2308 del_gendisk(ns->disk);
2295 nvme_ns_free(ns); 2309 if (!blk_queue_dying(ns->queue))
2310 blk_cleanup_queue(ns->queue);
2296 } 2311 }
2297} 2312}
2298 2313
@@ -2349,9 +2364,22 @@ static void nvme_release_instance(struct nvme_dev *dev)
2349 spin_unlock(&dev_list_lock); 2364 spin_unlock(&dev_list_lock);
2350} 2365}
2351 2366
2367static void nvme_free_namespaces(struct nvme_dev *dev)
2368{
2369 struct nvme_ns *ns, *next;
2370
2371 list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
2372 list_del(&ns->list);
2373 put_disk(ns->disk);
2374 kfree(ns);
2375 }
2376}
2377
2352static void nvme_free_dev(struct kref *kref) 2378static void nvme_free_dev(struct kref *kref)
2353{ 2379{
2354 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); 2380 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
2381
2382 nvme_free_namespaces(dev);
2355 kfree(dev->queues); 2383 kfree(dev->queues);
2356 kfree(dev->entry); 2384 kfree(dev->entry);
2357 kfree(dev); 2385 kfree(dev);
@@ -2525,6 +2553,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2525 goto release_pools; 2553 goto release_pools;
2526 } 2554 }
2527 2555
2556 kref_init(&dev->kref);
2528 result = nvme_dev_add(dev); 2557 result = nvme_dev_add(dev);
2529 if (result) 2558 if (result)
2530 goto shutdown; 2559 goto shutdown;
@@ -2540,11 +2569,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2540 goto remove; 2569 goto remove;
2541 2570
2542 dev->initialized = 1; 2571 dev->initialized = 1;
2543 kref_init(&dev->kref);
2544 return 0; 2572 return 0;
2545 2573
2546 remove: 2574 remove:
2547 nvme_dev_remove(dev); 2575 nvme_dev_remove(dev);
2576 nvme_free_namespaces(dev);
2548 shutdown: 2577 shutdown:
2549 nvme_dev_shutdown(dev); 2578 nvme_dev_shutdown(dev);
2550 release_pools: 2579 release_pools: