| From adfe4b7922c7f4213eba6d0492ab634853541f0f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 12 Apr 2021 10:40:02 +0200 |
| Subject: RDMA/rtrs-clt: destroy sysfs after removing session from active list |
| |
| From: Gioh Kim <gi-oh.kim@ionos.com> |
| |
| [ Upstream commit 7f4a8592ff29f19c5a2ca549d0973821319afaad ] |
| |
| A session can be removed dynamically by sysfs interface "remove_path" that |
| eventually calls rtrs_clt_remove_path_from_sysfs function. The current |
| rtrs_clt_remove_path_from_sysfs first removes the sysfs interfaces and |
| frees sess->stats object. Second it removes the session from the active |
| list. |
| |
| Therefore some functions could access non-connected session and access the |
| freed sess->stats object even-if they check the session status before |
| accessing the session. |
| |
| For instance rtrs_clt_request and get_next_path_min_inflight check the |
| session status and try to send IO to the session. The session status |
| could be changed when they are trying to send IO but they could not catch |
| the change and update the statistics information in sess->stats object, |
| and generate use-after-free problem. |
| (see: "RDMA/rtrs-clt: Check state of the rtrs_clt_sess before reading its |
| stats") |
| |
| This patch changes the rtrs_clt_remove_path_from_sysfs to remove the |
| session from the active session list and then destroy the sysfs |
| interfaces. |
| |
| Each function still should check the session status because closing or |
| error recovery paths can change the status. |
| |
| Fixes: 6a98d71daea1 ("RDMA/rtrs: client: main functionality") |
| Link: https://lore.kernel.org/r/20210412084002.33582-1-gi-oh.kim@ionos.com |
| Signed-off-by: Gioh Kim <gi-oh.kim@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> |
| --- |
| drivers/infiniband/ulp/rtrs/rtrs-clt.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c |
| index ee37c5af3a8c..4cd81d84cd18 100644 |
| --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c |
| +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c |
| @@ -2799,8 +2799,8 @@ int rtrs_clt_remove_path_from_sysfs(struct rtrs_clt_sess *sess, |
| } while (!changed && old_state != RTRS_CLT_DEAD); |
| |
| if (likely(changed)) { |
| - rtrs_clt_destroy_sess_files(sess, sysfs_self); |
| rtrs_clt_remove_path_from_arr(sess); |
| + rtrs_clt_destroy_sess_files(sess, sysfs_self); |
| kobject_put(&sess->kobj); |
| } |
| |
| -- |
| 2.30.2 |
| |