[PATCH net v5 1/2] net/smc: order the CDC receive path against RMB publication
From: Bryam Vargas via B4 Relay
Date: Thu Oct 15 2026 - 07:53:51 EST
From: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
smc_conn_create() adds an SMC-R connection to the token tree before
smc_buf_create() sets conn->rmb_desc. Tokens come from one global
counter, so a peer in the link group can predict the next one. A CDC
with that token, arriving in the window, makes
smc_cdc_msg_recv_action() dereference a NULL rmb_desc in softirq.
Set rmb_desc with a release store after the receive fields that go
with it, and drop a CDC in smc_cdc_rx_handler() while rmb_desc is
unset. A conforming peer learns the token only from the CLC accept or
confirm, sent after smc_buf_create(), so nothing it sends is dropped.
The SMC-D receive tasklet needs no check: smc_ism_set_conn() publishes
the connection under smcd->lock, which smcd_handle_irq() also takes.
Fixes: 69cb7dc0218b ("net/smc: add common buffer size in send and receive buffer descriptors")
Closes: https://sashiko.dev/#/patchset/20261008-b4-disp-f7cd3d96-v6-0-fba616c0920c@xxxxxxxxx?part=1
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
---
net/smc/smc_cdc.c | 6 +++++-
net/smc/smc_core.c | 3 ++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index 32d6d03df321..7bf902ebd7ab 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -483,7 +483,11 @@ static void smc_cdc_rx_handler(struct ib_wc *wc, void *buf)
lgr = smc_get_lgr(link);
read_lock_bh(&lgr->conns_lock);
conn = smc_lgr_find_conn(ntohl(cdc->token), lgr);
- if (!conn || conn->out_of_sync) {
+ /* The connection is in the token tree before __smc_buf_create()
+ * sets its RMB: drop a CDC that comes earlier. rmb_desc is never
+ * cleared, so the callees can load it plainly.
+ */
+ if (!conn || conn->out_of_sync || !smp_load_acquire(&conn->rmb_desc)) {
read_unlock_bh(&lgr->conns_lock);
return;
}
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 9974149659c2..26f19a00c159 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -2502,12 +2502,13 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
}
if (is_rmb) {
- conn->rmb_desc = buf_desc;
conn->rmbe_size_comp = bufsize_comp;
smc->sk.sk_rcvbuf = bufsize * 2;
atomic_set(&conn->bytes_to_rcv, 0);
conn->rmbe_update_limit =
smc_rmb_wnd_update_limit(buf_desc->len);
+ /* Set last; pairs with the acquire in smc_cdc_rx_handler() */
+ smp_store_release(&conn->rmb_desc, buf_desc);
if (is_smcd)
smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */
} else {
--
2.56.0