From 58aa8d11517d16a67fe19a2cb62266ad750adedc Mon Sep 17 00:00:00 2001 From: Guangguan Wang Date: Wed, 12 Jul 2023 13:06:00 +0800 Subject: [PATCH] anolis: net/smc: do not check diff_cons when rmb_desc is null When some smc sock is connecting, meanwhile smc_lgr_terminate happens because of remove rdma driver or other reasons. The smc sock need to be killed, which may calls smc_tx_rdma_write_with_no_data_rwwi to abort the connection. The smc sock in connecting may not process rmb create, and the rmb_desc pointer may be null, once the smc_tx_rdma_write_with_no_data_rwwi is called, the diff_cons will be checked, which is not needed, and will cause crash because of null pointer. So do not check diff_cons when rmb_desc is null when calling smc_tx_rdma_write_with_no_data_rwwi. The crash info show bellows: BUG: kernel NULL pointer dereference, address: 0000000000000020 PGD 10b7a7067 P4D 10b7a7067 PUD 13f866067 PMD 0 Oops: 0000 [#1] SMP NOPTI Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS 449e491 04/01/2014 Workqueue: events smc_lgr_terminate_work [smc] RIP: 0010:__smcr_tx_rdma_writes_rwwi+0x8e/0x410 [smc] RSP: 0018:ffffac66c4a0bd90 EFLAGS: 00010246 RAX: 0000000000400000 RBX: ffff8a8b082b60c8 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000002 RBP: 0000000000000000 R08: ffffac66c4a0bdd0 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001 R13: ffff8a8b25040440 R14: 0000000200000001 R15: ffff8a8b25040440 FS: 0000000000000000(0000) GS:ffff8a99c0900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000020 CR3: 000000010b0fa003 CR4: 0000000002770ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: smc_tx_rdma_write_with_no_data_rwwi.part.18+0x13a/0x1d0 [smc] smc_conn_kill+0x38/0xd0 [smc] __smc_lgr_terminate.part.38+0xc8/0x180 [smc] process_one_work+0x19b/0x340 worker_thread+0x30/0x370 ? process_one_work+0x340/0x340 kthread+0x114/0x130 ? __kthread_cancel_work+0x50/0x50 ret_from_fork+0x1f/0x30 Signed-off-by: Guangguan Wang --- net/smc/smc_tx.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index 0555f553824d..0506d76ea81c 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c @@ -376,7 +376,8 @@ static int __smcr_tx_rdma_writes_rwwi(struct smc_connection *conn, int dst_off, u8 saved_credits = 0; bool cr_flag = false; u8 conn_state_flags; - int diff_cons, rc; + int diff_cons = 0; + int rc; BUILD_BUG_ON_MSG(sizeof(union smc_wr_imm_msg) > sizeof(__be32), "sizeof(union smc_wr_imm_msg) can not exceed the size of imm_data(__be32)"); @@ -409,10 +410,11 @@ static int __smcr_tx_rdma_writes_rwwi(struct smc_connection *conn, int dst_off, if (conn_state_flags || prod_flags != urg_flags) imm_msg.hdr.opcode = SMC_WR_OP_CTRL; - smc_curs_copy(&cfed, &conn->local_tx_ctrl.cons, conn); - smc_curs_copy(&cons_old, &conn->rx_curs_confirmed, conn); - diff_cons = smc_curs_diff(conn->rmb_desc->len, &cons_old, - &conn->local_tx_ctrl.cons); + if (conn->rmb_desc) { + smc_curs_copy(&cfed, &conn->local_tx_ctrl.cons, conn); + smc_curs_copy(&cons_old, &conn->rx_curs_confirmed, conn); + diff_cons = smc_curs_diff(conn->rmb_desc->len, &cons_old, &cfed); + } switch (imm_msg.hdr.opcode) { case SMC_WR_OP_DATA: if (diff_cons > SMC_DATA_MAX_DIFF_CONS) @@ -462,7 +464,7 @@ static int __smcr_tx_rdma_writes_rwwi(struct smc_connection *conn, int dst_off, /* do not update rx_curs_confirmed if all flags equal to 0, * since diff_cons will not be carried by imm_data in this case. */ - if (update_rx_curs_confirmed) + if (update_rx_curs_confirmed && conn->rmb_desc) smc_curs_add(conn->rmb_desc->len, &conn->rx_curs_confirmed, diff_cons); } else { smc_wr_rx_put_credits(link, saved_credits); -- Gitee