OSDN Git Service

RDMA/core: Use refcount_t instead of atomic_t on refcount of iwpm_admin_data
authorWeihang Li <liweihang@huawei.com>
Fri, 28 May 2021 09:37:33 +0000 (17:37 +0800)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 8 Jun 2021 17:36:24 +0000 (14:36 -0300)
The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks. Increase refcount_t from 0 to 1 is
regarded as there is a risk about use-after-free. So it should be set to 1
directly during initialization.

Link: https://lore.kernel.org/r/1622194663-2383-3-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/iwpm_util.c
drivers/infiniband/core/iwpm_util.h

index f80e555..b8f40e6 100644 (file)
@@ -61,7 +61,7 @@ int iwpm_init(u8 nl_client)
 {
        int ret = 0;
        mutex_lock(&iwpm_admin_lock);
-       if (atomic_read(&iwpm_admin.refcount) == 0) {
+       if (!refcount_read(&iwpm_admin.refcount)) {
                iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE,
                                           sizeof(struct hlist_head),
                                           GFP_KERNEL);
@@ -77,8 +77,12 @@ int iwpm_init(u8 nl_client)
                        ret = -ENOMEM;
                        goto init_exit;
                }
+
+               refcount_set(&iwpm_admin.refcount, 1);
+       } else {
+               refcount_inc(&iwpm_admin.refcount);
        }
-       atomic_inc(&iwpm_admin.refcount);
+
 init_exit:
        mutex_unlock(&iwpm_admin_lock);
        if (!ret) {
@@ -105,12 +109,12 @@ int iwpm_exit(u8 nl_client)
        if (!iwpm_valid_client(nl_client))
                return -EINVAL;
        mutex_lock(&iwpm_admin_lock);
-       if (atomic_read(&iwpm_admin.refcount) == 0) {
+       if (!refcount_read(&iwpm_admin.refcount)) {
                mutex_unlock(&iwpm_admin_lock);
                pr_err("%s Incorrect usage - negative refcount\n", __func__);
                return -EINVAL;
        }
-       if (atomic_dec_and_test(&iwpm_admin.refcount)) {
+       if (refcount_dec_and_test(&iwpm_admin.refcount)) {
                free_hash_bucket();
                free_reminfo_bucket();
                pr_debug("%s: Resources are destroyed\n", __func__);
index eeb8e60..5002ac6 100644 (file)
@@ -90,7 +90,7 @@ struct iwpm_remote_info {
 };
 
 struct iwpm_admin_data {
-       atomic_t refcount;
+       refcount_t refcount;
        atomic_t nlmsg_seq;
        int      client_list[RDMA_NL_NUM_CLIENTS];
        u32      reg_list[RDMA_NL_NUM_CLIENTS];