[PATCH net] net/smc: guard the CDC receive path against an unset RMB

From: Bryam Vargas via B4 Relay

Date: Sat Jul 11 2026 - 03:45:38 EST


From: Bryam Vargas <hexlabsecurity@xxxxxxxxx>

The SMC CDC receive handlers look up a connection by its wire token and
then dereference conn->rmb_desc -- smcd_cdc_rx_tsklet() reads
rmb_desc->cpu_addr and smc_cdc_msg_recv_action() reads rmb_desc->len --
but a connection is published to the link group's token tree in
smc_conn_create(), before smc_buf_create() allocates its RMB. A peer
that sends a CDC message carrying the connection's token in that setup
window reaches the handlers with conn->rmb_desc still NULL and crashes
the host with a NULL pointer dereference.

Bail out of both receive handlers when the RMB is not yet allocated, as
they already do for a killed or out-of-sync connection.

Closes: https://sashiko.dev/#/patchset/20260705-b4-disp-28a1bbca-v4-1-be089b98acc6@xxxxxxxxx?part=1
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
---
Reachability is by source inspection: smc_conn_create() registers the
connection before smc_buf_create() allocates conn->rmb_desc, and the
receive handlers guard only !conn/out_of_sync/killed. Verified with an
in-kernel KASAN model reproducing the deref with rmb_desc == NULL (fault
at the ->len / ->cpu_addr offsets) and clean with the guard. af_smc runs
over an RDMA fabric or an ISM device, so this is the model rather than a
live trigger; reproducer available on request.

No Fixes: tag: the CDC receive path predates the history available here;
the introducing commits are the original CDC support and its SMC-D
addition -- please add whichever tag you prefer.
---
net/smc/smc_cdc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index 32d6d03df321..d60f68facbc3 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -446,7 +446,7 @@ static void smcd_cdc_rx_tsklet(struct tasklet_struct *t)
struct smcd_cdc_msg cdc;
struct smc_sock *smc;

- if (!conn || conn->killed)
+ if (!conn || conn->killed || !conn->rmb_desc)
return;

data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
@@ -483,7 +483,7 @@ 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) {
+ if (!conn || conn->out_of_sync || !conn->rmb_desc) {
read_unlock_bh(&lgr->conns_lock);
return;
}

---
base-commit: dd3210c47e8d3ac6b4e9141fc68acc03b38c0ba3
change-id: 20260711-b4-disp-c36a9798-1b35bd69fd72

Best regards,
--
Bryam Vargas <hexlabsecurity@xxxxxxxxx>