Skip to content

Commit 8700af2

Browse files
hiqbal-ionosjgunthorpe
authored andcommitted
RDMA/rtrs-clt: Fix possible double free in error case
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: eab0982 ("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>
1 parent 32f57cb commit 8700af2

1 file changed

Lines changed: 20 additions & 17 deletions

File tree

drivers/infiniband/ulp/rtrs/rtrs-clt.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,6 +2682,8 @@ static void rtrs_clt_dev_release(struct device *dev)
26822682
struct rtrs_clt_sess *clt = container_of(dev, struct rtrs_clt_sess,
26832683
dev);
26842684

2685+
mutex_destroy(&clt->paths_ev_mutex);
2686+
mutex_destroy(&clt->paths_mutex);
26852687
kfree(clt);
26862688
}
26872689

@@ -2711,6 +2713,8 @@ static struct rtrs_clt_sess *alloc_clt(const char *sessname, size_t paths_num,
27112713
return ERR_PTR(-ENOMEM);
27122714
}
27132715

2716+
clt->dev.class = rtrs_clt_dev_class;
2717+
clt->dev.release = rtrs_clt_dev_release;
27142718
uuid_gen(&clt->paths_uuid);
27152719
INIT_LIST_HEAD_RCU(&clt->paths_list);
27162720
clt->paths_num = paths_num;
@@ -2727,53 +2731,52 @@ static struct rtrs_clt_sess *alloc_clt(const char *sessname, size_t paths_num,
27272731
init_waitqueue_head(&clt->permits_wait);
27282732
mutex_init(&clt->paths_ev_mutex);
27292733
mutex_init(&clt->paths_mutex);
2734+
device_initialize(&clt->dev);
27302735

2731-
clt->dev.class = rtrs_clt_dev_class;
2732-
clt->dev.release = rtrs_clt_dev_release;
27332736
err = dev_set_name(&clt->dev, "%s", sessname);
27342737
if (err)
2735-
goto err;
2738+
goto err_put;
2739+
27362740
/*
27372741
* Suppress user space notification until
27382742
* sysfs files are created
27392743
*/
27402744
dev_set_uevent_suppress(&clt->dev, true);
2741-
err = device_register(&clt->dev);
2742-
if (err) {
2743-
put_device(&clt->dev);
2744-
goto err;
2745-
}
2745+
err = device_add(&clt->dev);
2746+
if (err)
2747+
goto err_put;
27462748

27472749
clt->kobj_paths = kobject_create_and_add("paths", &clt->dev.kobj);
27482750
if (!clt->kobj_paths) {
27492751
err = -ENOMEM;
2750-
goto err_dev;
2752+
goto err_del;
27512753
}
27522754
err = rtrs_clt_create_sysfs_root_files(clt);
27532755
if (err) {
27542756
kobject_del(clt->kobj_paths);
27552757
kobject_put(clt->kobj_paths);
2756-
goto err_dev;
2758+
goto err_del;
27572759
}
27582760
dev_set_uevent_suppress(&clt->dev, false);
27592761
kobject_uevent(&clt->dev.kobj, KOBJ_ADD);
27602762

27612763
return clt;
2762-
err_dev:
2763-
device_unregister(&clt->dev);
2764-
err:
2764+
err_del:
2765+
device_del(&clt->dev);
2766+
err_put:
27652767
free_percpu(clt->pcpu_path);
2766-
kfree(clt);
2768+
put_device(&clt->dev);
27672769
return ERR_PTR(err);
27682770
}
27692771

27702772
static void free_clt(struct rtrs_clt_sess *clt)
27712773
{
27722774
free_permits(clt);
27732775
free_percpu(clt->pcpu_path);
2774-
mutex_destroy(&clt->paths_ev_mutex);
2775-
mutex_destroy(&clt->paths_mutex);
2776-
/* release callback will free clt in last put */
2776+
2777+
/*
2778+
* release callback will free clt and destroy mutexes in last put
2779+
*/
27772780
device_unregister(&clt->dev);
27782781
}
27792782

0 commit comments

Comments
 (0)