From: Bryam Vargas <hexlabsecurity@proton.me>
To: "D . Wythe" <alibuda@linux.alibaba.com>,
Dust Li <dust.li@linux.alibaba.com>,
Sidraya Jayagond <sidraya@linux.ibm.com>,
Wenjia Zhang <wenjia@linux.ibm.com>
Cc: Mahanta Jambigi <mjambigi@linux.ibm.com>,
Tony Lu <tonylu@linux.alibaba.com>,
Wen Gu <guwen@linux.alibaba.com>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Stefan Raspl <raspl@linux.ibm.com>,
Ursula Braun <ubraun@linux.ibm.com>,
linux-rdma@vger.kernel.org, linux-s390@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] net/smc: bound the peer producer cursor on SMC-D and SMC-R CDC receive
Date: Wed, 10 Jun 2026 08:48:13 +0000 [thread overview]
Message-ID: <20260610084803.186516-1-hexlabsecurity@proton.me> (raw)
The SMC CDC receive path copies the peer's producer cursor -- a
wire-controlled value -- into the local connection cursor with no upper
bound against the receive buffer (RMB). A malicious peer can advertise a
producer cursor past rmb_desc->len, which is then used out of bounds:
- the urgent path uses the cursor count as a raw index:
smc_cdc_handle_urg_data_arrival() dereferences
*(rmb_desc->cpu_addr + rx_off + urg_curs.count - 1);
- the receive path turns the cursor into a length:
smc_cdc_msg_recv_action() feeds it to smc_curs_diff() and
atomic_add()s the result into conn->bytes_to_rcv. The differing-wrap
branch returns (len - old.count) + new.count, which exceeds len for a
forged cursor and accumulates across CDCs, so bytes_to_rcv grows past
rmb_desc->len even when the cursor count itself is bounded;
smc_rx_recvmsg() then copies the wrap-around second chunk past the RMB.
The RMB is a kernel allocation, so the reads disclose adjacent kernel
memory, and a cursor pointing at an unmapped offset faults in the receive
tasklet (softirq). Both transports are affected: SMC-D converts the
cursor in smcd_cdc_msg_to_host() and SMC-R in smc_cdc_cursor_to_host(),
and neither bounds the count.
Bound the producer cursor count to the RMB at both conversion boundaries
(this closes the urgent index on SMC-D and SMC-R) and enforce the
documented "0 <= bytes_to_rcv <= rmb_desc->len" invariant in
smc_cdc_msg_recv_action() (this closes the receive length, which the
cursor-count clamp alone cannot because of the differing-wrap diff and
the cumulative atomic_add).
Fixes: de8474eb9d50 ("net/smc: urgent data support")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
Reproduced under KASAN on 6.12.y. A forged producer cursor with
prod.count = rmb_desc->len + 1 and prod_flags.urg_data_present set produces
a 1-byte out-of-bounds read in smc_cdc_handle_urg_data_arrival()
(slab-out-of-bounds Read of size 1); the cursor-count clamp makes the same
input in-bounds. A wrap-flipped cursor drives bytes_to_rcv past
rmb_desc->len across several CDCs so smc_rx_recvmsg() over-reads; the
bytes_to_rcv invariant keeps it bounded. SMC-D was exercised over the
in-kernel loopback-ism and the SMC-R converter (smc_cdc_cursor_to_host)
over an emulated RDMA loopback. Clamping prod.count alone does not bound
the recv length, hence the separate bytes_to_rcv hunk.
net/smc/smc_cdc.c | 2 ++
net/smc/smc_cdc.h | 12 ++++++++++++
2 files changed, 14 insertions(+)
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index 619b3bab3824..738c45fd5cd0 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -382,6 +382,8 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
smp_mb__before_atomic();
atomic_add(diff_prod, &conn->bytes_to_rcv);
/* guarantee 0 <= bytes_to_rcv <= rmb_desc->len */
+ if (atomic_read(&conn->bytes_to_rcv) > conn->rmb_desc->len)
+ atomic_set(&conn->bytes_to_rcv, conn->rmb_desc->len);
smp_mb__after_atomic();
smc->sk.sk_data_ready(&smc->sk);
} else {
diff --git a/net/smc/smc_cdc.h b/net/smc/smc_cdc.h
index 696cc11f2303..7fa6e0d3817f 100644
--- a/net/smc/smc_cdc.h
+++ b/net/smc/smc_cdc.h
@@ -230,6 +230,12 @@ static inline void smc_cdc_cursor_to_host(union smc_host_cursor *local,
smc_curs_copy_net(&net, peer, conn);
temp.count = ntohl(net.count);
temp.wrap = ntohs(net.wrap);
+ /* the peer producer cursor is wire-controlled; bound the SMC-R count to
+ * our RMB before it is used as a raw index by the urgent path, mirroring
+ * the SMC-D conversion in smcd_cdc_msg_to_host().
+ */
+ if (temp.count > conn->rmb_desc->len)
+ temp.count = conn->rmb_desc->len;
if ((old.wrap > temp.wrap) && temp.wrap)
return;
if ((old.wrap == temp.wrap) &&
@@ -260,6 +266,12 @@ static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local,
temp.wrap = peer->prod.wrap;
temp.count = peer->prod.count;
+ /* the peer producer cursor is wire-controlled; a count past our RMB is
+ * used as a raw index by the urgent path (smc_cdc_handle_urg_data_arrival)
+ * and as a length by the recv path. Bound it to the RMB.
+ */
+ if (temp.count > conn->rmb_desc->len)
+ temp.count = conn->rmb_desc->len;
smc_curs_copy(&local->prod, &temp, conn);
temp.wrap = peer->cons.wrap;
--
2.43.0
reply other threads:[~2026-06-10 8:48 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260610084803.186516-1-hexlabsecurity@proton.me \
--to=hexlabsecurity@proton.me \
--cc=alibuda@linux.alibaba.com \
--cc=davem@davemloft.net \
--cc=dust.li@linux.alibaba.com \
--cc=edumazet@google.com \
--cc=guwen@linux.alibaba.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mjambigi@linux.ibm.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=raspl@linux.ibm.com \
--cc=sidraya@linux.ibm.com \
--cc=tonylu@linux.alibaba.com \
--cc=ubraun@linux.ibm.com \
--cc=wenjia@linux.ibm.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox