diff options
author | Yishai Hadas <yishaih@mellanox.com> | 2015-08-13 18:32:03 +0300 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2015-10-13 03:46:07 +0100 |
commit | cf50958a5affdc35f664b82c79d650cc9c83d499 (patch) | |
tree | ba2cf0fc3fec91cd7178d2c104ec311c94935052 /drivers/infiniband/core/uverbs.h | |
parent | 9421b777b8631dc79364c893e495a30e50ada77f (diff) | |
download | kernel_samsung_smdk4412-cf50958a5affdc35f664b82c79d650cc9c83d499.zip kernel_samsung_smdk4412-cf50958a5affdc35f664b82c79d650cc9c83d499.tar.gz kernel_samsung_smdk4412-cf50958a5affdc35f664b82c79d650cc9c83d499.tar.bz2 |
IB/uverbs: Fix race between ib_uverbs_open and remove_one
commit 35d4a0b63dc0c6d1177d4f532a9deae958f0662c upstream.
Fixes: 2a72f212263701b927559f6850446421d5906c41 ("IB/uverbs: Remove dev_table")
Before this commit there was a device look-up table that was protected
by a spin_lock used by ib_uverbs_open and by ib_uverbs_remove_one. When
it was dropped and container_of was used instead, it enabled the race
with remove_one as dev might be freed just after:
dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev) but
before the kref_get.
In addition, this buggy patch added some dead code as
container_of(x,y,z) can never be NULL and so dev can never be NULL.
As a result the comment above ib_uverbs_open saying "the open method
will either immediately run -ENXIO" is wrong as it can never happen.
The solution follows Jason Gunthorpe suggestion from below URL:
https://www.mail-archive.com/linux-rdma@vger.kernel.org/msg25692.html
cdev will hold a kref on the parent (the containing structure,
ib_uverbs_device) and only when that kref is released it is
guaranteed that open will never be called again.
In addition, fixes the active count scheme to use an atomic
not a kref to prevent WARN_ON as pointed by above comment
from Jason.
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Shachar Raindel <raindel@mellanox.com>
Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/infiniband/core/uverbs.h')
-rw-r--r-- | drivers/infiniband/core/uverbs.h | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 5bcb2af..228af18 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -69,7 +69,7 @@ */ struct ib_uverbs_device { - struct kref ref; + atomic_t refcount; int num_comp_vectors; struct completion comp; struct device *dev; @@ -78,6 +78,7 @@ struct ib_uverbs_device { struct cdev cdev; struct rb_root xrcd_tree; struct mutex xrcd_tree_mutex; + struct kobject kobj; }; struct ib_uverbs_event_file { |