Commit 622eab0a authored by Md Haris Iqbal's avatar Md Haris Iqbal Committed by Zheng Zengkai
Browse files

RDMA/rtrs-clt: Fix possible double free in error case

stable inclusion
from stable-v5.10.103
commit 8260f1800f83e667f26c80baa7f0b9d92ae271d7
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I52XLL
CVE: CVE-2022-29156

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8260f1800f83e667f26c80baa7f0b9d92ae271d7

--------------------------------

[ Upstream commit 8700af2c ]

Callback function rtrs_clt_dev_release() for put_device() calls kfree(clt)
to free memory. We shouldn't call kfree(clt) again, and we can't use the
clt after kfree too.

Replace device_register() with device_initialize() and device_add() so that
dev_set_name can() be used appropriately.

Move mutex_destroy() to the release function so it can be called in
the alloc_clt err path.

Fixes: eab09824 ("RDMA/rtrs-clt: Refactor the failure cases in alloc_clt")
Link: https://lore.kernel.org/r/20220217030929.323849-1-haris.iqbal@ionos.com


Reported-by: default avatarMiaoqian Lin <linmq006@gmail.com>
Signed-off-by: default avatarMd Haris Iqbal <haris.iqbal@ionos.com>
Reviewed-by: default avatarJack Wang <jinpu.wang@ionos.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarChen Jun <chenjun102@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: default avatarXiu Jianfeng <xiujianfeng@huawei.com>
parent 58a96eb9
Loading
Loading
Loading
Loading
+20 −17
Original line number Diff line number Diff line
@@ -2540,6 +2540,8 @@ static void rtrs_clt_dev_release(struct device *dev)
{
	struct rtrs_clt *clt = container_of(dev, struct rtrs_clt, dev);

	mutex_destroy(&clt->paths_ev_mutex);
	mutex_destroy(&clt->paths_mutex);
	kfree(clt);
}

@@ -2571,6 +2573,8 @@ static struct rtrs_clt *alloc_clt(const char *sessname, size_t paths_num,
		return ERR_PTR(-ENOMEM);
	}

	clt->dev.class = rtrs_clt_dev_class;
	clt->dev.release = rtrs_clt_dev_release;
	uuid_gen(&clt->paths_uuid);
	INIT_LIST_HEAD_RCU(&clt->paths_list);
	clt->paths_num = paths_num;
@@ -2588,43 +2592,41 @@ static struct rtrs_clt *alloc_clt(const char *sessname, size_t paths_num,
	init_waitqueue_head(&clt->permits_wait);
	mutex_init(&clt->paths_ev_mutex);
	mutex_init(&clt->paths_mutex);
	device_initialize(&clt->dev);

	clt->dev.class = rtrs_clt_dev_class;
	clt->dev.release = rtrs_clt_dev_release;
	err = dev_set_name(&clt->dev, "%s", sessname);
	if (err)
		goto err;
		goto err_put;

	/*
	 * Suppress user space notification until
	 * sysfs files are created
	 */
	dev_set_uevent_suppress(&clt->dev, true);
	err = device_register(&clt->dev);
	if (err) {
		put_device(&clt->dev);
		goto err;
	}
	err = device_add(&clt->dev);
	if (err)
		goto err_put;

	clt->kobj_paths = kobject_create_and_add("paths", &clt->dev.kobj);
	if (!clt->kobj_paths) {
		err = -ENOMEM;
		goto err_dev;
		goto err_del;
	}
	err = rtrs_clt_create_sysfs_root_files(clt);
	if (err) {
		kobject_del(clt->kobj_paths);
		kobject_put(clt->kobj_paths);
		goto err_dev;
		goto err_del;
	}
	dev_set_uevent_suppress(&clt->dev, false);
	kobject_uevent(&clt->dev.kobj, KOBJ_ADD);

	return clt;
err_dev:
	device_unregister(&clt->dev);
err:
err_del:
	device_del(&clt->dev);
err_put:
	free_percpu(clt->pcpu_path);
	kfree(clt);
	put_device(&clt->dev);
	return ERR_PTR(err);
}

@@ -2643,9 +2645,10 @@ static void free_clt(struct rtrs_clt *clt)
	wait_for_inflight_permits(clt);
	free_permits(clt);
	free_percpu(clt->pcpu_path);
	mutex_destroy(&clt->paths_ev_mutex);
	mutex_destroy(&clt->paths_mutex);
	/* release callback will free clt in last put */

	/*
	 * release callback will free clt and destroy mutexes in last put
	 */
	device_unregister(&clt->dev);
}