mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 01:04:19 +08:00
RDMA/rtrs-clt: Fix possible double free in error case
[ Upstream commit8700af2cc1
] 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:eab0982466
("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: Miaoqian Lin <linmq006@gmail.com> Signed-off-by: Md Haris Iqbal <haris.iqbal@ionos.com> Reviewed-by: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
ff999198ec
commit
bf2cfad0c6
@ -2664,6 +2664,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);
|
||||
}
|
||||
|
||||
@ -2693,6 +2695,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;
|
||||
@ -2709,43 +2713,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);
|
||||
}
|
||||
|
||||
@ -2753,9 +2755,10 @@ static void free_clt(struct rtrs_clt *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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user