Commit fcc57a7b authored by Weihang Li's avatar Weihang Li Committed by Jason Gunthorpe
Browse files

RDMA/core: Use refcount_t instead of atomic_t on refcount of iwpm_admin_data

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: default avatarWeihang Li <liweihang@huawei.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 60dff56d
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -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__);
+1 −1
Original line number Diff line number Diff line
@@ -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];