diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2017-03-17 14:48:09 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-20 08:28:41 -0400 |
| commit | 8dd114ef78c855814558472ed13e99357e098e33 (patch) | |
| tree | e756e2487da8dc19c0811fda9585e189d78c7a0c /drivers/dax | |
| parent | 6240377c574b06c5ef900cab3be2625e482ae8bf (diff) | |
device-dax: fix cdev leak
commit ed01e50acdd3e4a640cf9ebd28a7e810c3ceca97 upstream.
If device_add() fails, cleanup the cdev. Otherwise, we leak a kobj_map()
with a stale device number.
As Jason points out, there is a small possibility that userspace has
opened and mapped the device in the time between cdev_add() and the
device_add() failure. We need a new kill_dax_dev() helper to invalidate
any established mappings.
Fixes: ba09c01d2fa8 ("dax: convert to the cdev api")
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/dax')
| -rw-r--r-- | drivers/dax/dax.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 193224889e41..586f9543de73 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c | |||
| @@ -553,13 +553,10 @@ static void dax_dev_release(struct device *dev) | |||
| 553 | kfree(dax_dev); | 553 | kfree(dax_dev); |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | static void unregister_dax_dev(void *dev) | 556 | static void kill_dax_dev(struct dax_dev *dax_dev) |
| 557 | { | 557 | { |
| 558 | struct dax_dev *dax_dev = to_dax_dev(dev); | ||
| 559 | struct cdev *cdev = &dax_dev->cdev; | 558 | struct cdev *cdev = &dax_dev->cdev; |
| 560 | 559 | ||
| 561 | dev_dbg(dev, "%s\n", __func__); | ||
| 562 | |||
| 563 | /* | 560 | /* |
| 564 | * Note, rcu is not protecting the liveness of dax_dev, rcu is | 561 | * Note, rcu is not protecting the liveness of dax_dev, rcu is |
| 565 | * ensuring that any fault handlers that might have seen | 562 | * ensuring that any fault handlers that might have seen |
| @@ -571,6 +568,15 @@ static void unregister_dax_dev(void *dev) | |||
| 571 | synchronize_srcu(&dax_srcu); | 568 | synchronize_srcu(&dax_srcu); |
| 572 | unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1); | 569 | unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1); |
| 573 | cdev_del(cdev); | 570 | cdev_del(cdev); |
| 571 | } | ||
| 572 | |||
| 573 | static void unregister_dax_dev(void *dev) | ||
| 574 | { | ||
| 575 | struct dax_dev *dax_dev = to_dax_dev(dev); | ||
| 576 | |||
| 577 | dev_dbg(dev, "%s\n", __func__); | ||
| 578 | |||
| 579 | kill_dax_dev(dax_dev); | ||
| 574 | device_unregister(dev); | 580 | device_unregister(dev); |
| 575 | } | 581 | } |
| 576 | 582 | ||
| @@ -647,6 +653,7 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region, | |||
| 647 | dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id); | 653 | dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id); |
| 648 | rc = device_add(dev); | 654 | rc = device_add(dev); |
| 649 | if (rc) { | 655 | if (rc) { |
| 656 | kill_dax_dev(dax_dev); | ||
| 650 | put_device(dev); | 657 | put_device(dev); |
| 651 | return ERR_PTR(rc); | 658 | return ERR_PTR(rc); |
| 652 | } | 659 | } |
