From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Wen Gu <guwen@linux.alibaba.com>,
"David S . Miller" <davem@davemloft.net>,
Sasha Levin <sashal@kernel.org>,
kgraul@linux.ibm.com, kuba@kernel.org,
linux-s390@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH AUTOSEL 5.16 10/19] net/smc: Resolve the race between SMC-R link access and clear
Date: Sat, 22 Jan 2022 19:11:03 -0500 [thread overview]
Message-ID: <20220123001113.2460140-10-sashal@kernel.org> (raw)
In-Reply-To: <20220123001113.2460140-1-sashal@kernel.org>
From: Wen Gu <guwen@linux.alibaba.com>
[ Upstream commit 20c9398d3309d170300d67643b851fd26783af24 ]
We encountered some crashes caused by the race between SMC-R
link access and link clear that triggered by abnormal link
group termination, such as port error.
Here is an example of this kind of crashes:
BUG: kernel NULL pointer dereference, address: 0000000000000000
Workqueue: smc_hs_wq smc_listen_work [smc]
RIP: 0010:smc_llc_flow_initiate+0x44/0x190 [smc]
Call Trace:
<TASK>
? __smc_buf_create+0x75a/0x950 [smc]
smcr_lgr_reg_rmbs+0x2a/0xbf [smc]
smc_listen_work+0xf72/0x1230 [smc]
? process_one_work+0x25c/0x600
process_one_work+0x25c/0x600
worker_thread+0x4f/0x3a0
? process_one_work+0x600/0x600
kthread+0x15d/0x1a0
? set_kthread_struct+0x40/0x40
ret_from_fork+0x1f/0x30
</TASK>
smc_listen_work() __smc_lgr_terminate()
---------------------------------------------------------------
| smc_lgr_free()
| |- smcr_link_clear()
| |- memset(lnk, 0)
smc_listen_rdma_reg() |
|- smcr_lgr_reg_rmbs() |
|- smc_llc_flow_initiate() |
|- access lnk->lgr (panic) |
These crashes are similarly caused by clearing SMC-R link
resources when some functions is still accessing to them.
This patch tries to fix the issue by introducing reference
count of SMC-R links and ensuring that the sensitive resources
of links won't be cleared until reference count reaches zero.
The operation to the SMC-R link reference count can be concluded
as follows:
object [hold or initialized as 1] [put]
--------------------------------------------------------------------
links smcr_link_init() smcr_link_clear()
connections smc_conn_create() smc_conn_free()
Through this way, the clear of SMC-R links is later than the
free of all the smc connections above it, thus avoiding the
unsafe reference to SMC-R links.
Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/smc_core.c | 52 +++++++++++++++++++++++++++++++++++-----------
net/smc/smc_core.h | 4 ++++
2 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 84b89d13c3359..f4de45ac88189 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -745,6 +745,8 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
}
get_device(&lnk->smcibdev->ibdev->dev);
atomic_inc(&lnk->smcibdev->lnk_cnt);
+ refcount_set(&lnk->refcnt, 1); /* link refcnt is set to 1 */
+ lnk->clearing = 0;
lnk->path_mtu = lnk->smcibdev->pattr[lnk->ibport - 1].active_mtu;
lnk->link_id = smcr_next_link_id(lgr);
lnk->lgr = lgr;
@@ -994,8 +996,12 @@ void smc_switch_link_and_count(struct smc_connection *conn,
struct smc_link *to_lnk)
{
atomic_dec(&conn->lnk->conn_cnt);
+ /* link_hold in smc_conn_create() */
+ smcr_link_put(conn->lnk);
conn->lnk = to_lnk;
atomic_inc(&conn->lnk->conn_cnt);
+ /* link_put in smc_conn_free() */
+ smcr_link_hold(conn->lnk);
}
struct smc_link *smc_switch_conns(struct smc_link_group *lgr,
@@ -1152,6 +1158,8 @@ void smc_conn_free(struct smc_connection *conn)
if (!lgr->conns_num)
smc_lgr_schedule_free_work(lgr);
lgr_put:
+ if (!lgr->is_smcd)
+ smcr_link_put(conn->lnk); /* link_hold in smc_conn_create() */
smc_lgr_put(lgr); /* lgr_hold in smc_conn_create() */
}
@@ -1208,22 +1216,11 @@ static void smcr_rtoken_clear_link(struct smc_link *lnk)
}
}
-/* must be called under lgr->llc_conf_mutex lock */
-void smcr_link_clear(struct smc_link *lnk, bool log)
+static void __smcr_link_clear(struct smc_link *lnk)
{
struct smc_link_group *lgr = lnk->lgr;
struct smc_ib_device *smcibdev;
- if (!lgr || lnk->state == SMC_LNK_UNUSED)
- return;
- lnk->peer_qpn = 0;
- smc_llc_link_clear(lnk, log);
- smcr_buf_unmap_lgr(lnk);
- smcr_rtoken_clear_link(lnk);
- smc_ib_modify_qp_error(lnk);
- smc_wr_free_link(lnk);
- smc_ib_destroy_queue_pair(lnk);
- smc_ib_dealloc_protection_domain(lnk);
smc_wr_free_link_mem(lnk);
smc_ibdev_cnt_dec(lnk);
put_device(&lnk->smcibdev->ibdev->dev);
@@ -1235,6 +1232,35 @@ void smcr_link_clear(struct smc_link *lnk, bool log)
smc_lgr_put(lgr); /* lgr_hold in smcr_link_init() */
}
+/* must be called under lgr->llc_conf_mutex lock */
+void smcr_link_clear(struct smc_link *lnk, bool log)
+{
+ if (!lnk->lgr || lnk->clearing ||
+ lnk->state == SMC_LNK_UNUSED)
+ return;
+ lnk->clearing = 1;
+ lnk->peer_qpn = 0;
+ smc_llc_link_clear(lnk, log);
+ smcr_buf_unmap_lgr(lnk);
+ smcr_rtoken_clear_link(lnk);
+ smc_ib_modify_qp_error(lnk);
+ smc_wr_free_link(lnk);
+ smc_ib_destroy_queue_pair(lnk);
+ smc_ib_dealloc_protection_domain(lnk);
+ smcr_link_put(lnk); /* theoretically last link_put */
+}
+
+void smcr_link_hold(struct smc_link *lnk)
+{
+ refcount_inc(&lnk->refcnt);
+}
+
+void smcr_link_put(struct smc_link *lnk)
+{
+ if (refcount_dec_and_test(&lnk->refcnt))
+ __smcr_link_clear(lnk);
+}
+
static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb,
struct smc_buf_desc *buf_desc)
{
@@ -1872,6 +1898,8 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
goto out;
}
smc_lgr_hold(conn->lgr); /* lgr_put in smc_conn_free() */
+ if (!conn->lgr->is_smcd)
+ smcr_link_hold(conn->lnk); /* link_put in smc_conn_free() */
conn->freed = 0;
conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE;
conn->local_tx_ctrl.len = SMC_WR_TX_SIZE;
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index 51203b16307be..e73217f52f3dd 100644
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -137,6 +137,8 @@ struct smc_link {
u8 peer_link_uid[SMC_LGR_ID_SIZE]; /* peer uid */
u8 link_idx; /* index in lgr link array */
u8 link_is_asym; /* is link asymmetric? */
+ u8 clearing : 1; /* link is being cleared */
+ refcount_t refcnt; /* link reference count */
struct smc_link_group *lgr; /* parent link group */
struct work_struct link_down_wrk; /* wrk to bring link down */
char ibname[IB_DEVICE_NAME_MAX]; /* ib device name */
@@ -504,6 +506,8 @@ void smc_core_exit(void);
int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
u8 link_idx, struct smc_init_info *ini);
void smcr_link_clear(struct smc_link *lnk, bool log);
+void smcr_link_hold(struct smc_link *lnk);
+void smcr_link_put(struct smc_link *lnk);
void smc_switch_link_and_count(struct smc_connection *conn,
struct smc_link *to_lnk);
int smcr_buf_map_lgr(struct smc_link *lnk);
--
2.34.1
next prev parent reply other threads:[~2022-01-23 0:12 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-23 0:10 [PATCH AUTOSEL 5.16 01/19] remoteproc: coredump: Correct argument 2 type for memcpy_fromio Sasha Levin
2022-01-23 0:10 ` [PATCH AUTOSEL 5.16 02/19] hwspinlock: stm32: enable clock at probe Sasha Levin
2022-01-23 0:10 ` Sasha Levin
2022-01-23 0:10 ` [f2fs-dev] [PATCH AUTOSEL 5.16 03/19] f2fs: don't drop compressed page cache in .{invalidate, release}page Sasha Levin
2022-01-23 0:10 ` [PATCH AUTOSEL 5.16 03/19] f2fs: don't drop compressed page cache in .{invalidate,release}page Sasha Levin
2022-01-23 0:10 ` [PATCH AUTOSEL 5.16 04/19] riscv: dts: microchip: mpfs: Fix reference clock node Sasha Levin
2022-01-23 0:10 ` Sasha Levin
2022-01-23 0:10 ` [PATCH AUTOSEL 5.16 05/19] ksmbd: smbd: call rdma_accept() under CM handler Sasha Levin
2022-01-23 0:10 ` [PATCH AUTOSEL 5.16 06/19] x86/PCI: Ignore E820 reservations for bridge windows on newer systems Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 07/19] sit: allow encapsulated IPv6 traffic to be delivered locally Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 08/19] ceph: don't check for quotas on MDS stray dirs Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 09/19] net/smc: Resolve the race between link group access and termination Sasha Levin
2022-01-23 0:11 ` Sasha Levin [this message]
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 11/19] net: apple: mace: Fix build since dev_addr constification Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 12/19] net: apple: bmac: " Sasha Levin
2022-01-24 15:52 ` Jakub Kicinski
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 13/19] net/mlx5_vdpa: Offer VIRTIO_NET_F_MTU when setting MTU Sasha Levin
2022-01-23 0:11 ` Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 14/19] virtio-pci: fix the confusing error message Sasha Levin
2022-01-23 0:11 ` Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 15/19] vhost/test: fix memory leak of vhost virtqueues Sasha Levin
2022-01-23 0:11 ` Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 16/19] vdpa: clean up get_config_size ret value handling Sasha Levin
2022-01-23 0:11 ` Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 17/19] vdpa/mlx5: Fix is_index_valid() to refer to features Sasha Levin
2022-01-23 0:11 ` Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 18/19] io_uring: perform poll removal even if async work removal is successful Sasha Levin
2022-01-23 0:11 ` [PATCH AUTOSEL 5.16 19/19] block: Fix wrong offset in bio_truncate() Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220123001113.2460140-10-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=davem@davemloft.net \
--cc=guwen@linux.alibaba.com \
--cc=kgraul@linux.ibm.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.