RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_uverbs_device
authorWeihang Li <liweihang@huawei.com>
Fri, 28 May 2021 09:37:38 +0000 (17:37 +0800)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 8 Jun 2021 18:04:36 +0000 (15:04 -0300)
The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Link: https://lore.kernel.org/r/1622194663-2383-8-git-send-email-liweihang@huawei.com
Signed-off-by: Weihang Li <liweihang@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_main.c

index 53a1047..821d93c 100644 (file)
@@ -97,7 +97,7 @@ ib_uverbs_init_udata_buf_or_null(struct ib_udata *udata,
  */
 
 struct ib_uverbs_device {
-       atomic_t                                refcount;
+       refcount_t                              refcount;
        u32                                     num_comp_vectors;
        struct completion                       comp;
        struct device                           dev;
index f173ecd..d544340 100644 (file)
@@ -197,7 +197,7 @@ void ib_uverbs_release_file(struct kref *ref)
                module_put(ib_dev->ops.owner);
        srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
 
-       if (atomic_dec_and_test(&file->device->refcount))
+       if (refcount_dec_and_test(&file->device->refcount))
                ib_uverbs_comp_dev(file->device);
 
        if (file->default_async_file)
@@ -891,7 +891,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        int srcu_key;
 
        dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
-       if (!atomic_inc_not_zero(&dev->refcount))
+       if (!refcount_inc_not_zero(&dev->refcount))
                return -ENXIO;
 
        get_device(&dev->dev);
@@ -955,7 +955,7 @@ err_module:
 err:
        mutex_unlock(&dev->lists_mutex);
        srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
-       if (atomic_dec_and_test(&dev->refcount))
+       if (refcount_dec_and_test(&dev->refcount))
                ib_uverbs_comp_dev(dev);
 
        put_device(&dev->dev);
@@ -1124,7 +1124,7 @@ static int ib_uverbs_add_one(struct ib_device *device)
        uverbs_dev->dev.release = ib_uverbs_release_dev;
        uverbs_dev->groups[0] = &dev_attr_group;
        uverbs_dev->dev.groups = uverbs_dev->groups;
-       atomic_set(&uverbs_dev->refcount, 1);
+       refcount_set(&uverbs_dev->refcount, 1);
        init_completion(&uverbs_dev->comp);
        uverbs_dev->xrcd_tree = RB_ROOT;
        mutex_init(&uverbs_dev->xrcd_tree_mutex);
@@ -1166,7 +1166,7 @@ static int ib_uverbs_add_one(struct ib_device *device)
 err_uapi:
        ida_free(&uverbs_ida, devnum);
 err:
-       if (atomic_dec_and_test(&uverbs_dev->refcount))
+       if (refcount_dec_and_test(&uverbs_dev->refcount))
                ib_uverbs_comp_dev(uverbs_dev);
        wait_for_completion(&uverbs_dev->comp);
        put_device(&uverbs_dev->dev);
@@ -1229,7 +1229,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
                wait_clients = 0;
        }
 
-       if (atomic_dec_and_test(&uverbs_dev->refcount))
+       if (refcount_dec_and_test(&uverbs_dev->refcount))
                ib_uverbs_comp_dev(uverbs_dev);
        if (wait_clients)
                wait_for_completion(&uverbs_dev->comp);