* [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure
@ 2026-10-31 14:14 Guangshuo Li
2026-11-09 11:16 ` Leon Romanovsky
0 siblings, 1 reply; 4+ messages in thread
From: Guangshuo Li @ 2026-10-31 14:14 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Guangshuo Li, stable, Md. Haris Iqbal, Jack Wang,
Leon Romanovsky, linux-rdma, linux-kernel
rtrs_clt_create_path_files() drops the path reference on failure, but
its callers still close connections and free the path. This can access
freed memory and free the path twice.
Keep the caller's path reference until its cleanup completes. Move
per-CPU stats cleanup to the path release callback and let the embedded
stats kobject hold a path reference until its own release callback, so
delayed kobject release cannot outlive the enclosing allocation. Keep
direct cleanup for failures before the path kobject is initialized.
This issue was found by our static analysis tool under development.
Fixes: 215378b838df ("RDMA/rtrs: client: sysfs interface functions")
Cc: stable@vger.kernel.org
Assisted-by: OpenAI:gpt-6-astra
Signed-off-by: Guangshuo Li <liguangshuo@mail.sdu.edu.cn>
---
Build-tested the changed objects with x86_64 allmodconfig (W=1):
GCC with CONFIG_DEBUG_KOBJECT_RELEASE=n/y, and Clang with it enabled.
A host harness executing extracted cleanup functions passed 198
failure/teardown cases, including delayed release (also under ASan/UBSan).
No kernel runtime or RDMA hardware testing was performed.
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 10 +++++++---
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 14 ++++++++++----
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
index f8b833bd81ad..44edc405f400 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
@@ -22,6 +22,7 @@ static void rtrs_clt_path_release(struct kobject *kobj)
clt_path = container_of(kobj, struct rtrs_clt_path, kobj);
+ free_percpu(clt_path->stats->pcpu_stats);
free_path(clt_path);
}
@@ -32,11 +33,13 @@ static struct kobj_type ktype_sess = {
static void rtrs_clt_path_stats_release(struct kobject *kobj)
{
+ struct rtrs_clt_path *clt_path;
struct rtrs_clt_stats *stats;
stats = container_of(kobj, struct rtrs_clt_stats, kobj_stats);
- free_percpu(stats->pcpu_stats);
+ clt_path = container_of_const(stats, struct rtrs_clt_path, stats[0]);
+ kobject_put(&clt_path->kobj);
}
static struct kobj_type ktype_stats = {
@@ -422,6 +425,7 @@ static const struct attribute_group rtrs_clt_path_attr_group = {
.attrs = rtrs_clt_path_attrs,
};
+/* The caller retains the initial path reference on all exits. */
int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
{
struct rtrs_clt_sess *clt = clt_path->clt;
@@ -438,7 +442,6 @@ int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
"%s", str);
if (err) {
pr_err("kobject_init_and_add: %pe\n", ERR_PTR(err));
- kobject_put(&clt_path->kobj);
return err;
}
err = sysfs_create_group(&clt_path->kobj, &rtrs_clt_path_attr_group);
@@ -446,6 +449,8 @@ int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
pr_err("sysfs_create_group(): %pe\n", ERR_PTR(err));
goto put_kobj;
}
+ /* Keep the path alive until its embedded stats kobject is released. */
+ kobject_get(&clt_path->kobj);
err = kobject_init_and_add(&clt_path->stats->kobj_stats, &ktype_stats,
&clt_path->kobj, "stats");
if (err) {
@@ -470,7 +475,6 @@ int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
sysfs_remove_group(&clt_path->kobj, &rtrs_clt_path_attr_group);
put_kobj:
kobject_del(&clt_path->kobj);
- kobject_put(&clt_path->kobj);
return err;
}
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index bf3a0377da3f..547313136598 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -2880,8 +2880,7 @@ struct rtrs_clt_sess *rtrs_clt_open(struct rtrs_clt_ops *ops,
if (err) {
list_del_rcu(&clt_path->s.entry);
rtrs_clt_close_conns(clt_path, true);
- free_percpu(clt_path->stats->pcpu_stats);
- free_path(clt_path);
+ kobject_put(&clt_path->kobj);
goto close_all_path;
}
}
@@ -3161,7 +3160,7 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt_sess *clt,
err = init_path(clt_path);
if (err)
- goto close_path;
+ goto close_path_free;
err = rtrs_clt_create_path_files(clt_path);
if (err)
@@ -3169,12 +3168,19 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt_sess *clt,
return 0;
-close_path:
+close_path_free:
rtrs_clt_remove_path_from_arr(clt_path);
rtrs_clt_close_conns(clt_path, true);
free_percpu(clt_path->stats->pcpu_stats);
free_path(clt_path);
+ return err;
+
+close_path:
+ rtrs_clt_remove_path_from_arr(clt_path);
+ rtrs_clt_close_conns(clt_path, true);
+ kobject_put(&clt_path->kobj);
+
return err;
}
base-commit: d89e1d186ec9271bf78e62771779e9fc03bf0fc3
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure
2026-10-31 14:14 [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure Guangshuo Li
@ 2026-11-09 11:16 ` Leon Romanovsky
2026-11-09 12:56 ` 李广硕
0 siblings, 1 reply; 4+ messages in thread
From: Leon Romanovsky @ 2026-11-09 11:16 UTC (permalink / raw)
To: Guangshuo Li
Cc: Jason Gunthorpe, stable, Md. Haris Iqbal, Jack Wang, linux-rdma,
linux-kernel
On Sat, Oct 31, 2026 at 10:14:46PM +0800, Guangshuo Li wrote:
> rtrs_clt_create_path_files() drops the path reference on failure, but
> its callers still close connections and free the path. This can access
> freed memory and free the path twice.
Sorry, but how?
>
> Keep the caller's path reference until its cleanup completes. Move
> per-CPU stats cleanup to the path release callback and let the embedded
> stats kobject hold a path reference until its own release callback, so
> delayed kobject release cannot outlive the enclosing allocation. Keep
> direct cleanup for failures before the path kobject is initialized.
>
> This issue was found by our static analysis tool under development.
It looks like false positive.
Thanks
>
> Fixes: 215378b838df ("RDMA/rtrs: client: sysfs interface functions")
> Cc: stable@vger.kernel.org
> Assisted-by: OpenAI:gpt-6-astra
> Signed-off-by: Guangshuo Li <liguangshuo@mail.sdu.edu.cn>
> ---
> Build-tested the changed objects with x86_64 allmodconfig (W=1):
> GCC with CONFIG_DEBUG_KOBJECT_RELEASE=n/y, and Clang with it enabled.
> A host harness executing extracted cleanup functions passed 198
> failure/teardown cases, including delayed release (also under ASan/UBSan).
> No kernel runtime or RDMA hardware testing was performed.
>
> drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 10 +++++++---
> drivers/infiniband/ulp/rtrs/rtrs-clt.c | 14 ++++++++++----
> 2 files changed, 17 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
> index f8b833bd81ad..44edc405f400 100644
> --- a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
> +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
> @@ -22,6 +22,7 @@ static void rtrs_clt_path_release(struct kobject *kobj)
>
> clt_path = container_of(kobj, struct rtrs_clt_path, kobj);
>
> + free_percpu(clt_path->stats->pcpu_stats);
> free_path(clt_path);
> }
>
> @@ -32,11 +33,13 @@ static struct kobj_type ktype_sess = {
>
> static void rtrs_clt_path_stats_release(struct kobject *kobj)
> {
> + struct rtrs_clt_path *clt_path;
> struct rtrs_clt_stats *stats;
>
> stats = container_of(kobj, struct rtrs_clt_stats, kobj_stats);
>
> - free_percpu(stats->pcpu_stats);
> + clt_path = container_of_const(stats, struct rtrs_clt_path, stats[0]);
> + kobject_put(&clt_path->kobj);
> }
>
> static struct kobj_type ktype_stats = {
> @@ -422,6 +425,7 @@ static const struct attribute_group rtrs_clt_path_attr_group = {
> .attrs = rtrs_clt_path_attrs,
> };
>
> +/* The caller retains the initial path reference on all exits. */
> int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
> {
> struct rtrs_clt_sess *clt = clt_path->clt;
> @@ -438,7 +442,6 @@ int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
> "%s", str);
> if (err) {
> pr_err("kobject_init_and_add: %pe\n", ERR_PTR(err));
> - kobject_put(&clt_path->kobj);
> return err;
> }
> err = sysfs_create_group(&clt_path->kobj, &rtrs_clt_path_attr_group);
> @@ -446,6 +449,8 @@ int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
> pr_err("sysfs_create_group(): %pe\n", ERR_PTR(err));
> goto put_kobj;
> }
> + /* Keep the path alive until its embedded stats kobject is released. */
> + kobject_get(&clt_path->kobj);
> err = kobject_init_and_add(&clt_path->stats->kobj_stats, &ktype_stats,
> &clt_path->kobj, "stats");
> if (err) {
> @@ -470,7 +475,6 @@ int rtrs_clt_create_path_files(struct rtrs_clt_path *clt_path)
> sysfs_remove_group(&clt_path->kobj, &rtrs_clt_path_attr_group);
> put_kobj:
> kobject_del(&clt_path->kobj);
> - kobject_put(&clt_path->kobj);
>
> return err;
> }
> diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
> index bf3a0377da3f..547313136598 100644
> --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
> +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
> @@ -2880,8 +2880,7 @@ struct rtrs_clt_sess *rtrs_clt_open(struct rtrs_clt_ops *ops,
> if (err) {
> list_del_rcu(&clt_path->s.entry);
> rtrs_clt_close_conns(clt_path, true);
> - free_percpu(clt_path->stats->pcpu_stats);
> - free_path(clt_path);
> + kobject_put(&clt_path->kobj);
> goto close_all_path;
> }
> }
> @@ -3161,7 +3160,7 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt_sess *clt,
>
> err = init_path(clt_path);
> if (err)
> - goto close_path;
> + goto close_path_free;
>
> err = rtrs_clt_create_path_files(clt_path);
> if (err)
> @@ -3169,12 +3168,19 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt_sess *clt,
>
> return 0;
>
> -close_path:
> +close_path_free:
> rtrs_clt_remove_path_from_arr(clt_path);
> rtrs_clt_close_conns(clt_path, true);
> free_percpu(clt_path->stats->pcpu_stats);
> free_path(clt_path);
>
> + return err;
> +
> +close_path:
> + rtrs_clt_remove_path_from_arr(clt_path);
> + rtrs_clt_close_conns(clt_path, true);
> + kobject_put(&clt_path->kobj);
> +
> return err;
> }
>
>
> base-commit: d89e1d186ec9271bf78e62771779e9fc03bf0fc3
^ permalink raw reply [flat|nested] 4+ messages in thread* Re:Re: [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure
2026-11-09 11:16 ` Leon Romanovsky
@ 2026-11-09 12:56 ` 李广硕
2026-11-12 19:09 ` Leon Romanovsky
0 siblings, 1 reply; 4+ messages in thread
From: 李广硕 @ 2026-11-09 12:56 UTC (permalink / raw)
To: Leon Romanovsky
Cc: Jason Gunthorpe, stable, Md. Haris Iqbal, Jack Wang, linux-rdma,
linux-kernel
Hi Leon,
Thanks for reviewing.
From: Leon Romanovsky <leon@kernel.org>
Date: 2026-11-09 19:16:52
To: Guangshuo Li <liguangshuo@mail.sdu.edu.cn>
Cc: Jason Gunthorpe <jgg@ziepe.ca>,stable@vger.kernel.org,"Md. Haris Iqbal" <haris.iqbal@ionos.com>,Jack Wang <jinpu.wang@ionos.com>,linux-rdma@vger.kernel.org,linux-kernel@vger.kernel.org
Subject: Re: [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure>On Sat, Oct 31, 2026 at 10:14:46PM +0800, Guangshuo Li wrote:
>> rtrs_clt_create_path_files() drops the path reference on failure, but
>> its callers still close connections and free the path. This can access
>> freed memory and free the path twice.
>
>Sorry, but how?
>
Consider an allocation failure while setting the name of the path
kobject in rtrs_clt_create_path_files(). kobject_init_and_add() has
already initialized the reference count to one when setting the name
fails with -ENOMEM. The stats kobject has not been created yet, and
adding the path to clt->paths_list did not take a kobject reference.
The error branch then calls kobject_put(&clt_path->kobj). This drops
the only reference. With CONFIG_DEBUG_KOBJECT_RELEASE=n,
rtrs_clt_path_release() runs synchronously and calls free_path(), which
does kfree(clt_path).
Back in rtrs_clt_open(), the first statement on that error path is:
list_del_rcu(&clt_path->s.entry);
That accesses the list node embedded in the path that was just freed.
This is the use-after-free I meant.
Thanks,
Guangshuo
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: Re: [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure
2026-11-09 12:56 ` 李广硕
@ 2026-11-12 19:09 ` Leon Romanovsky
0 siblings, 0 replies; 4+ messages in thread
From: Leon Romanovsky @ 2026-11-12 19:09 UTC (permalink / raw)
To: 李广硕
Cc: Jason Gunthorpe, stable, Md. Haris Iqbal, Jack Wang, linux-rdma,
linux-kernel
On Mon, Nov 09, 2026 at 08:56:46PM +0800, 李广硕 wrote:
> Hi Leon,
>
> Thanks for reviewing.
>
> From: Leon Romanovsky <leon@kernel.org>
> Date: 2026-11-09 19:16:52
> To: Guangshuo Li <liguangshuo@mail.sdu.edu.cn>
> Cc: Jason Gunthorpe <jgg@ziepe.ca>,stable@vger.kernel.org,"Md. Haris Iqbal" <haris.iqbal@ionos.com>,Jack Wang <jinpu.wang@ionos.com>,linux-rdma@vger.kernel.org,linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure>On Sat, Oct 31, 2026 at 10:14:46PM +0800, Guangshuo Li wrote:
> >> rtrs_clt_create_path_files() drops the path reference on failure, but
> >> its callers still close connections and free the path. This can access
> >> freed memory and free the path twice.
> >
> >Sorry, but how?
> >
> Consider an allocation failure while setting the name of the path
> kobject in rtrs_clt_create_path_files(). kobject_init_and_add() has
> already initialized the reference count to one when setting the name
> fails with -ENOMEM. The stats kobject has not been created yet, and
> adding the path to clt->paths_list did not take a kobject reference.
>
> The error branch then calls kobject_put(&clt_path->kobj). This drops
> the only reference. With CONFIG_DEBUG_KOBJECT_RELEASE=n,
> rtrs_clt_path_release() runs synchronously and calls free_path(), which
> does kfree(clt_path).
>
> Back in rtrs_clt_open(), the first statement on that error path is:
>
> list_del_rcu(&clt_path->s.entry);
>
> That accesses the list node embedded in the path that was just freed.
> This is the use-after-free I meant.
The error handling appears to be incorrect. rtrs_clt_create_path_files()
should undo only the changes it made internally and error handling of
call to rtrs_clt_create_path_files() should undo what was done in
rtrs_clt_open().
Thanks
>
> Thanks,
> Guangshuo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-12 19:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-31 14:14 [PATCH] RDMA/rtrs: Fix potential use-after-free on client sysfs setup failure Guangshuo Li
2026-11-09 11:16 ` Leon Romanovsky
2026-11-09 12:56 ` 李广硕
2026-11-12 19:09 ` Leon Romanovsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®