All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Bryam Vargas" <hexlabsecurity@proton.me>
Cc: linux-s390@vger.kernel.org,
	"Christian Borntraeger" <borntraeger@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	"Alexander Gordeev" <agordeev@linux.ibm.com>,
	linux-rdma@vger.kernel.org
Subject: Re: [PATCH net v6 2/3] net/smc: bound the receive length to the RMB in smc_rx_recvmsg()
Date: Fri, 09 Oct 2026 06:12:46 +0000	[thread overview]
Message-ID: <sashiko-outbox-164918@kernel.org> (raw)
In-Reply-To: <20261008-b4-disp-f7cd3d96-v6-2-fba616c0920c@proton.me>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] net/smc: OOB read in smc_rx_recvmsg due to MSG_PEEK/splice offset accumulation
- [Low] net/smc: invariant violation by subtracting from negative bytes_to_rcv
--

commit aad1c57ecb0dbd6966f102b6de4c64311cbb32d2
Author: Bryam Vargas <hexlabsecurity@proton.me>

net/smc: bound the receive length to the RMB in smc_rx_recvmsg()

conn->bytes_to_rcv is accumulated in the receive tasklet from the peer's
wire-controlled producer cursor via smc_curs_diff(), whose
differing-wrap branch can exceed rmb_desc->len; a forged cursor drives
bytes_to_rcv past the RMB, and over many CDC messages overflows the
signed counter negative. smc_rx_recvmsg() reads it as the readable
length and does a wrap-around copy whose second chunk is not re-bounded
to rmb_desc->len.

> diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
> index 197fddc6271f0..f781d7229185c 100644
> --- a/net/smc/smc_rx.c
> +++ b/net/smc/smc_rx.c
> @@ -442,6 +442,18 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
>  		/* initialize variables for 1st iteration of subsequent loop */
>  		/* could be just 1 byte, even after waiting on data above */
>  		readable = smc_rx_data_available(conn, peeked_bytes);
> +		/* bytes_to_rcv is accumulated from the peer's wire-controlled
> +		 * producer cursor; a forged cursor can drive it past the RMB,
> +		 * or overflow the signed accumulator to a negative value across
> +		 * many CDC messages (which a plain "> len" check would miss
> +		 * before the size_t cast below turns it huge).  Bound it to the
> +		 * RMB in either case so the wrap-around copy cannot run past
> +		 * rmb_desc->len.  This enforces the documented
> +		 * 0 <= bytes_to_rcv <= rmb_desc->len invariant at the consumer,
> +		 * race-free against the producer update in the receive tasklet.
> +		 */
> +		if (readable < 0 || readable > conn->rmb_desc->len)
> +			readable = conn->rmb_desc->len;

[Severity: High]
Does this code introduce an out-of-bounds read due to MSG_PEEK or splice
offset accumulation?

If bytes_to_rcv is inflated by a forged cursor to a value much larger than
rmb_desc->len, readable is clamped here. However, MSG_PEEK accumulates
peeked_bytes and splice() accumulates splbytes across loops.

These accumulated values are added to the local cursor using smc_curs_add():

net/smc/smc_rx.c:smc_rx_recvmsg() {
	...
		if ((flags & MSG_PEEK) && peeked_bytes)
			smc_curs_add(conn->rmb_desc->len, &cons, peeked_bytes);
		/* subsequent splice() calls pick up where previous left */
		if (splbytes)
			smc_curs_add(conn->rmb_desc->len, &cons, splbytes);
	...
}

Because smc_curs_add() only performs a single wrap-around subtraction:

net/smc/smc_cdc.h:smc_curs_add() {
	...
	curs->count += value;
	if (curs->count >= size) {
		curs->wrap++;
		curs->count -= size;
	}
	...
}

If peeked_bytes or splbytes exceeds 2 * rmb_desc->len, cons.count
fails to wrap completely and remains >= rmb_desc->len.

This causes the bounds check calculation to underflow into a huge size_t
value, bypassing the checks and copying out of bounds:

net/smc/smc_rx.c:smc_rx_recvmsg() {
	...
		chunk_len = min_t(size_t, copylen, conn->rmb_desc->len -
				  cons.count);
	...
}

[Severity: Low]
Does this clamp completely repair the invariant for bytes_to_rcv?

While readable is clamped to a positive value here, atomic_sub() is later
performed on the underlying bytes_to_rcv counter using copylen (which
is derived from readable):

net/smc/smc_rx.c:smc_rx_recvmsg() {
	...
		/* update cursors */
		if (!(flags & MSG_PEEK)) {
			/* increased in recv tasklet smc_cdc_msg_rcv() */
			smp_mb__before_atomic();
			atomic_sub(copylen, &conn->bytes_to_rcv);
			/* guarantee 0 <= bytes_to_rcv <= rmb_desc->len */
	...
}

If bytes_to_rcv was already driven negative by a forged cursor,
subtracting a positive copylen from it drives the atomic counter further
negative. This seems to violate the 0 <= bytes_to_rcv <= rmb_desc->len
invariant that the patch explicitly claims to guarantee.

>  		splbytes = atomic_read(&conn->splice_pending);
>  		if (!readable || (msg && splbytes)) {
>  			if (splbytes)

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261008-b4-disp-f7cd3d96-v6-0-fba616c0920c@proton.me?part=2

  reply	other threads:[~2026-10-09  6:12 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08  6:12 [PATCH net v6 0/3] net/smc: bound wire-controlled CDC cursors against the local buffers Bryam Vargas via B4 Relay
2026-10-08  6:12 ` Bryam Vargas
2026-10-08  6:12 ` [PATCH net v6 1/3] net/smc: bound the wire-controlled producer cursor to the RMB Bryam Vargas via B4 Relay
2026-10-08  6:12   ` Bryam Vargas
2026-10-09  6:12   ` sashiko-bot
2026-10-09  6:41   ` netdev-bot+sashiko
2026-10-08  6:12 ` [PATCH net v6 2/3] net/smc: bound the receive length to the RMB in smc_rx_recvmsg() Bryam Vargas via B4 Relay
2026-10-08  6:12   ` Bryam Vargas
2026-10-09  6:12   ` sashiko-bot [this message]
2026-10-09  6:41   ` netdev-bot+sashiko
2026-10-08  6:12 ` [PATCH net v6 3/3] net/smc: bound the send length to the send buffer in smc_tx_sendmsg() Bryam Vargas via B4 Relay
2026-10-08  6:12   ` Bryam Vargas
2026-10-09  6:12   ` sashiko-bot
2026-10-09  6:41   ` netdev-bot+sashiko
2026-10-08  6:15 ` [PATCH net v6 0/3] net/smc: bound wire-controlled CDC cursors against the local buffers netdev-bot+sinfo

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=sashiko-outbox-164918@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=hexlabsecurity@proton.me \
    --cc=linux-rdma@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.