From: Karsten Graul <kgraul@linux.ibm.com>
Subject: net/smc: use after free fix in smc_wr_tx_put_slot()
Patch-mainline: v4.20-rc4
Git-commit: e438bae43c1e08e688c09c410407b59fc1c173b4
References: FATE#325698, LTC#167867, bsc#1113481
Description: net/smc: bugfix and compatibility patches
Symptom: Random hangs in smc processing:
user space application hangs in socket send() or recv() call or
does never get a notification from a select() call.
Missing compatibility to other platforms:
confirm rkey and delete rkey processing is required by the
design, but delete rkey processing is missing. This leads to
protocol failures when communicating with other platforms like
zOS. The SMC-D shutdown signal support is missing, so there is
no detection if the remote peer closed the link group.
Broken administration of available WR send payload buffers due to
a use-after-free condition.
Problem: Misbehaviour regarding the user space api can lead to hang
situations. SMC is not fully compatible to some other platforms
due to missing rkey processing and SMC-D shutdown signal support.
Solution: Fixed protocoll deficiencies by implementing the required rkey
processing. For SMC-D, the cursors are now handled atomically to
handle parallel modifications. The SMC-D shutdown signal is now
processed when received and sent to the remote peer if needed.
Prereq patches are included.
Reproduction: Run SMC on a loaded system against zOS as peer system.
Upstream-Description:
net/smc: use after free fix in smc_wr_tx_put_slot()
In smc_wr_tx_put_slot() field pend->idx is used after being
cleared. That means always idx 0 is cleared in the wr_tx_mask.
This results in a broken administration of available WR send
payload buffers.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
net/smc/smc_wr.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -214,12 +214,14 @@ int smc_wr_tx_put_slot(struct smc_link *
pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv);
if (pend->idx < link->wr_tx_cnt) {
+ u32 idx = pend->idx;
+
/* clear the full struct smc_wr_tx_pend including .priv */
memset(&link->wr_tx_pends[pend->idx], 0,
sizeof(link->wr_tx_pends[pend->idx]));
memset(&link->wr_tx_bufs[pend->idx], 0,
sizeof(link->wr_tx_bufs[pend->idx]));
- test_and_clear_bit(pend->idx, link->wr_tx_mask);
+ test_and_clear_bit(idx, link->wr_tx_mask);
return 1;
}