* [PATCH net] RDS/IB: validate receive completion payload length
@ 2026-10-06 20:52 sungbyeongchan
2026-10-06 20:55 ` netdev-bot+sinfo
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: sungbyeongchan @ 2026-10-06 20:52 UTC (permalink / raw)
To: Allison Henderson, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Andy Grover
Cc: netdev, linux-rdma, rds-devel, linux-kernel
An RDS/RDMA peer can declare a fragment length larger than the payload
reported by the receive completion. The receive path attaches the recycled
receive fragment without validating those lengths, allowing recvmsg() to
return stale bytes beyond the actual payload.
Validate data_len against the expected current-fragment length before
transferring fragment ownership. Disconnect and reconnect on mismatch.
The issue reproduced in two clean QEMU boots. A peer declared 4096 bytes
while posting only 16 bytes, and a receiver under a different UID obtained
4080-byte tails from prior messages in all 256 attempts in each boot. With
this change, the malformed message was not delivered, reconnection
succeeded, and a subsequent normal 4096-byte message was delivered intact.
Fixes: 1e23b3ee0e94 ("RDS/IB: Receive datagrams via IB")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: sungbyeongchan <tjdqudcks0424@naver.com>
---
net/rds/ib_recv.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index bd6cb3ffaa571..0daddb108c8a7 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn,
}
}
+ if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) {
+ rds_ib_conn_error(conn,
+ "incoming fragment payload length %u, expected %u; "
+ "disconnecting and reconnecting\n",
+ data_len,
+ min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE));
+ goto done;
+ }
+
list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags);
recv->r_frag = NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-06 20:52 [PATCH net] RDS/IB: validate receive completion payload length sungbyeongchan @ 2026-10-06 20:55 ` netdev-bot+sinfo 2026-10-07 1:13 ` Allison Henderson 2026-10-09 11:52 ` netdev-bot+sashiko 2 siblings, 0 replies; 9+ messages in thread From: netdev-bot+sinfo @ 2026-10-06 20:55 UTC (permalink / raw) To: sungbyeongchan Cc: Allison Henderson, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover, netdev, linux-rdma, rds-devel, linux-kernel Hi! This is an automated message. This series looks like a fix, but its commit messages seem to be missing some information: - How the issue was discovered, e.g. hit in production, hit during development, syzbot report, manual code inspection, LLM or static analysis tool scan. Please do not repost the series just to address the above. Instead, reply to this email with the missing information, so that reviewers can take it into account. If the series needs another revision for other reasons, please include the information in the commit messages then. The evaluation is done by an LLM so it may be wrong, if you think that is the case please reply and explain. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-06 20:52 [PATCH net] RDS/IB: validate receive completion payload length sungbyeongchan 2026-10-06 20:55 ` netdev-bot+sinfo @ 2026-10-07 1:13 ` Allison Henderson 2026-10-16 20:18 ` [rds-devel] [External] : " Gerd Rausch 2026-10-09 11:52 ` netdev-bot+sashiko 2 siblings, 1 reply; 9+ messages in thread From: Allison Henderson @ 2026-10-07 1:13 UTC (permalink / raw) To: sungbyeongchan, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover Cc: netdev, linux-rdma, rds-devel, linux-kernel On Wed, 2026-10-07 at 05:52 +0900, sungbyeongchan wrote: > An RDS/RDMA peer can declare a fragment length larger than the payload > reported by the receive completion. The receive path attaches the recycled > receive fragment without validating those lengths, allowing recvmsg() to > return stale bytes beyond the actual payload. > > Validate data_len against the expected current-fragment length before > transferring fragment ownership. Disconnect and reconnect on mismatch. > > The issue reproduced in two clean QEMU boots. A peer declared 4096 bytes > while posting only 16 bytes, and a receiver under a different UID obtained > 4080-byte tails from prior messages in all 256 attempts in each boot. With > this change, the malformed message was not delivered, reconnection > succeeded, and a subsequent normal 4096-byte message was delivered intact. > > Fixes: 1e23b3ee0e94 ("RDS/IB: Receive datagrams via IB") > Cc: stable@vger.kernel.org > Assisted-by: LLM > Signed-off-by: sungbyeongchan <tjdqudcks0424@naver.com> Hi Sungbyeongchan, Thanks for sending this, and for following up on the earlier feedback so quickly. However, I realized after I sent it that another contributor had already publicly sent an equivalent fix earlier today, and the convention is to take the first correct patch on the list. https://lore.kernel.org/netdev/20261006125720.81227-1-shubham@octane.security/ So no need to follow up with the sashiko review, and I apologize for the miss-communication, but I will ask your Reported-by tag to be applied since you were the first to report the same bug. This was a solid find, and the reproduction was very well done. Please continue to send RDS fixes as you find them. Thank you! Allison > --- > net/rds/ib_recv.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c > index bd6cb3ffaa571..0daddb108c8a7 100644 > --- a/net/rds/ib_recv.c > +++ b/net/rds/ib_recv.c > @@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn, > } > } > > + if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) { > + rds_ib_conn_error(conn, > + "incoming fragment payload length %u, expected %u; " > + "disconnecting and reconnecting\n", > + data_len, > + min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)); > + goto done; > + } > + > list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags); > recv->r_frag = NULL; > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rds-devel] [External] : Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-07 1:13 ` Allison Henderson @ 2026-10-16 20:18 ` Gerd Rausch 2026-10-18 5:38 ` Allison Henderson 0 siblings, 1 reply; 9+ messages in thread From: Gerd Rausch @ 2026-10-16 20:18 UTC (permalink / raw) To: Allison Henderson, sungbyeongchan, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover Cc: netdev, linux-rdma, rds-devel, linux-kernel Hi, On 2026-10-06 18:13, Allison Henderson via rds-devel wrote: >> --- a/net/rds/ib_recv.c >> +++ b/net/rds/ib_recv.c >> @@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn, >> } >> } >> >> + if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) { >> + rds_ib_conn_error(conn, >> + "incoming fragment payload length %u, expected %u; " >> + "disconnecting and reconnecting\n", >> + data_len, >> + min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)); >> + goto done; >> + } >> + >> list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags); >> recv->r_frag = NULL; >> How does forcing a reconnect help this situation? After the reconnect, the sender submits the exact same (incorrect) message again, which it kept in "cp_retrans". Therefore, the exact same conditional triggers again. All but the last fragment of an RDS/IB message are expected to be of RDS_FRAG_SIZE. While there's no good protocol specification (to the best of my knowledge), posting an insufficiently large message can be seen as protocol violation. Therefore, apart from security concerns, the previous behavior of garbage-in / garbage-out is IMO better than this behavior of just endlessly forcing a reconnect. If there's a strong desire to address this issue, the sender should be told to discard the message. A reconnect doesn't address this issue. Thanks, Gerd ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rds-devel] [External] : Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-16 20:18 ` [rds-devel] [External] : " Gerd Rausch @ 2026-10-18 5:38 ` Allison Henderson 2026-10-18 18:32 ` Gerd Rausch 0 siblings, 1 reply; 9+ messages in thread From: Allison Henderson @ 2026-10-18 5:38 UTC (permalink / raw) To: Gerd Rausch, sungbyeongchan, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover Cc: netdev, linux-rdma, rds-devel, linux-kernel On Fri, 2026-10-16 at 13:18 -0700, Gerd Rausch wrote: > Hi, > > On 2026-10-06 18:13, Allison Henderson via rds-devel wrote: > > > --- a/net/rds/ib_recv.c > > > +++ b/net/rds/ib_recv.c > > > @@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn, > > > } > > > } > > > > > > + if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) { > > > + rds_ib_conn_error(conn, > > > + "incoming fragment payload length %u, expected %u; " > > > + "disconnecting and reconnecting\n", > > > + data_len, > > > + min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)); > > > + goto done; > > > + } > > > + > > > list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags); > > > recv->r_frag = NULL; > > > > How does forcing a reconnect help this situation? > > After the reconnect, the sender submits the exact same (incorrect) message again, > which it kept in "cp_retrans". > > Therefore, the exact same conditional triggers again. > > All but the last fragment of an RDS/IB message are expected to be of RDS_FRAG_SIZE. > > While there's no good protocol specification (to the best of my knowledge), > posting an insufficiently large message can be seen as protocol violation. > Hi Gerd, First, some bookkeeping to catch up with: this patch was submitted slightly after Shubham's "RDS/IB: validate receive fragment completions", which effectively the same patch. Shubham's variant went through a few revisions on netdev and is now in the net tree as 65cf6863606b. It varies only slightly, so your questions still apply, but to a different patch and one that's already merged: https://lore.kernel.org/netdev/20261013025729.40815-1-shubham@octane.security/ On the retransmit loop: cp_retrans only matters if the sender is our own RDS stack, and our stack can't produce the fragment this check rejects. rds_ib_xmit() posts every fragment but the last at RDS_FRAG_SIZE, because the scatterlist entries it works from are full pages except the final one. It even BUG_ONs if it's ever asked to resume a message at an offset that isn't a multiple of RDS_FRAG_SIZE, which can only hold if everything sent so far went out in full fragments. MSG_ZEROCOPY is the only path that produces odd-sized entries, and rds_sendmsg() refuses it for anything but TCP. So a Linux peer never trips this, before or after a reconnect. The peer that does trip it is already off the protocol, as you say, and whatever it retransmits isn't governed by our cp_retrans. > Therefore, apart from security concerns, the previous behavior of garbage-in / garbage-out > is IMO better than this behavior of just endlessly forcing a reconnect. The trouble is that the garbage going out wasn't the sender's. The receiver delivered h_len bytes of a page that only had data_len bytes written into it, so the tail was whatever the page held before: an earlier message to another socket (the report demonstrated this across UIDs), or unzeroed memory on a fresh page. That's the bug. And refusing to deliver it is the whole fix. Dropping the connection is also what rds_ib_process_recv() has always done for the neighbouring case, a fragment whose header doesn't match the message in progress. That check has been there since 1e23b3ee0e94 and has the same "a misbehaving peer can keep us reconnecting" property. This patch doesn't add a new failure mode, it just closes the one way a malformed fragment could still get through. > > If there's a strong desire to address this issue, the sender should be > told to discard the message. A reconnect doesn't address this issue. > I don't think there's a way to say that today. The RDS header flags are congestion-bitmap, ack-required, retransmitted and the extension-header bit. The only error a receiver can signal to its peer is to drop the connection. A per-message reject would be a protocol extension that both ends have to implement. But that would be net-next material, and it couldn't help against the only peers that actually send these. I'd be happy to review it if someone wants to take it on, but I don't think it should hold up a stable fix for a data disclosure. Hope that helps! Allison > Thanks, > > Gerd > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rds-devel] [External] : Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-18 5:38 ` Allison Henderson @ 2026-10-18 18:32 ` Gerd Rausch 2026-10-19 22:44 ` Allison Henderson 0 siblings, 1 reply; 9+ messages in thread From: Gerd Rausch @ 2026-10-18 18:32 UTC (permalink / raw) To: Allison Henderson Cc: sungbyeongchan, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, rds-devel@oss.oracle.com, linux-kernel@vger.kernel.org Hi Allison, > On Oct 17, 2026, at 22:38, Allison Henderson <achender@kernel.org> wrote: > On Fri, 2026-10-16 at 13:18 -0700, Gerd Rausch wrote: >> >> On 2026-10-06 18:13, Allison Henderson via rds-devel wrote: >>>> --- a/net/rds/ib_recv.c >>>> +++ b/net/rds/ib_recv.c >>>> @@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn, >>>> } >>>> } >>>> >>>> + if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) { >>>> + rds_ib_conn_error(conn, >>>> + "incoming fragment payload length %u, expected %u; " >>>> + "disconnecting and reconnecting\n", >>>> + data_len, >>>> + min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)); >>>> + goto done; >>>> + } >>>> + >>>> list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags); >>>> recv->r_frag = NULL; >>>> >> How does forcing a reconnect help this situation? >> [...] > > On the retransmit loop: cp_retrans only matters if the sender is our > own RDS stack, and our stack can't produce the fragment this check > rejects. Correct. But this check was presumably added for a reason. 1) An incorrect implementation of RDS (other than the one we're looking at) 2) A bad actor, intentionally crafting such messages. >> Therefore, apart from security concerns, the previous behavior of garbage-in / garbage-out >> is IMO better than this behavior of just endlessly forcing a reconnect. > > The trouble is that the garbage going out wasn't the sender's. The > receiver delivered h_len bytes of a page that only had data_len bytes > written into it, so the tail was whatever the page held before: an > earlier message to another socket (the report demonstrated this across > UIDs), or unzeroed memory on a fresh page. That's the bug. And > refusing to deliver it is the whole fix. Wait. This patch was created for a hypothetical case, no? Based on analysis of "Assisted-by: LLM". This patch does *not* refuse to deliver the bogus message. That would have been a fine choice. This patch just drops the underlying connection, in the hopes that when this message gets sent again, it'll somehow be different. What would make it different? Some unknown and non-deterministic sender? > > Dropping the connection is also what rds_ib_process_recv() has always > done for the neighbouring case, a fragment whose header doesn't match > the message in progress. That check has been there since 1e23b3ee0e94 > and has the same "a misbehaving peer can keep us reconnecting" > property. This patch doesn't add a new failure mode, it just closes > the one way a malformed fragment could still get through. How much benefit a 16bit IPv4 checksum calculation adds on top of the underlying InifiniBand CRC-32 protection is debatable. But let's just say somehow (I don't know how) the CRC-32 check missed a header corruption that ip_fast_csum() catches: You're correct, the connection would be dropped. So the assumption here is that this is a transport error, that fixes itself with a retransmit, and not that it's a bogus or malicious sender. Does this patch also assume we're looking at a transport error, that the CRC-32 didn't catch, and consider that more likely than a bad or malicious sender? I suggest that just dropping this message, not tearing down the connection, would have been a much better choice here. >> > >> If there's a strong desire to address this issue, the sender should be >> told to discard the message. A reconnect doesn't address this issue. >> > I don't think there's a way to say that today. The RDS header flags are > congestion-bitmap, ack-required, retransmitted and the extension-header > bit. The only error a receiver can signal to its peer is to drop the > connection. > Not exactly true. There's already code for the RDMA_CM_EVENT_REJECTED case to downgrade protocol version. The RDS code can be changed. The RDS protocol can be extended. A receiver could be made to tell a sender to drop a message, if we'd consider that beneficial. But in this case, since the message itself violates the "unwritten rules" of the RDS protocol, I'd say just dropping the message would be been a fine choice. Dropping the connection however, doesn't do anything. It just asks the sender to send the same bogus message again. > A per-message reject would be a protocol extension that both ends have to > implement. But that would be net-next material, and it couldn't help > against the only peers that actually send these. I'd be happy to review it > if someone wants to take it on, but I don't think it should hold up a stable > fix for a data disclosure. > Again, we don't need to do that. Dropping the message would have been a fine choice here. Thanks, Gerd ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rds-devel] [External] : Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-18 18:32 ` Gerd Rausch @ 2026-10-19 22:44 ` Allison Henderson 2026-10-19 23:31 ` Gerd Rausch 0 siblings, 1 reply; 9+ messages in thread From: Allison Henderson @ 2026-10-19 22:44 UTC (permalink / raw) To: Gerd Rausch Cc: sungbyeongchan, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, rds-devel@oss.oracle.com, linux-kernel@vger.kernel.org On Sun, 2026-10-18 at 18:32 +0000, Gerd Rausch wrote: > Hi Allison, > > > On Oct 17, 2026, at 22:38, Allison Henderson <achender@kernel.org> wrote: > > On Fri, 2026-10-16 at 13:18 -0700, Gerd Rausch wrote: > > > > > > On 2026-10-06 18:13, Allison Henderson via rds-devel wrote: > > > > > --- a/net/rds/ib_recv.c > > > > > +++ b/net/rds/ib_recv.c > > > > > @@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn, > > > > > } > > > > > } > > > > > > > > > > + if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) { > > > > > + rds_ib_conn_error(conn, > > > > > + "incoming fragment payload length %u, expected %u; " > > > > > + "disconnecting and reconnecting\n", > > > > > + data_len, > > > > > + min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)); > > > > > + goto done; > > > > > + } > > > > > + > > > > > list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags); > > > > > recv->r_frag = NULL; > > > > > > > > How does forcing a reconnect help this situation? > > > > > [...] > > > > > On the retransmit loop: cp_retrans only matters if the sender is our > > own RDS stack, and our stack can't produce the fragment this check > > rejects. > > Correct. But this check was presumably added for a reason. > > 1) An incorrect implementation of RDS (other than the one we're looking at) > 2) A bad actor, intentionally crafting such messages. > > > > Therefore, apart from security concerns, the previous behavior of garbage-in / garbage-out > > > is IMO better than this behavior of just endlessly forcing a reconnect. > > > > The trouble is that the garbage going out wasn't the sender's. The > > receiver delivered h_len bytes of a page that only had data_len bytes > > written into it, so the tail was whatever the page held before: an > > earlier message to another socket (the report demonstrated this across > > UIDs), or unzeroed memory on a fresh page. That's the bug. And > > refusing to deliver it is the whole fix. > > Wait. This patch was created for a hypothetical case, no? > Based on analysis of "Assisted-by: LLM". Per Documents/process/coding-assistants.rst it means an LLM contributed in some way, but sungbyeongchan patch had a reproducer and Shubham validated it under KMSAN > > This patch does *not* refuse to deliver the bogus message. > That would have been a fine choice. > > This patch just drops the underlying connection, in the hopes > that when this message gets sent again, it'll somehow be different. The short fragment is never linked, and the half-built inc is freed when the connection shuts down, so it doesn't reach the socket. > > What would make it different? > Some unknown and non-deterministic sender? > > > > > Dropping the connection is also what rds_ib_process_recv() has always > > done for the neighbouring case, a fragment whose header doesn't match > > the message in progress. That check has been there since 1e23b3ee0e94 > > and has the same "a misbehaving peer can keep us reconnecting" > > property. This patch doesn't add a new failure mode, it just closes > > the one way a malformed fragment could still get through. > > How much benefit a 16bit IPv4 checksum calculation adds on top of > the underlying InifiniBand CRC-32 protection is debatable. > > But let's just say somehow (I don't know how) the CRC-32 check missed > a header corruption that ip_fast_csum() catches: > You're correct, the connection would be dropped. > So the assumption here is that this is a transport error, > that fixes itself with a retransmit, and not that it's a bogus > or malicious sender. > > Does this patch also assume we're looking at a transport > error, that the CRC-32 didn't catch, and consider that more likely > than a bad or malicious sender? > > I suggest that just dropping this message, not tearing down the connection, > would have been a much better choice here. > > > > > > > > > If there's a strong desire to address this issue, the sender should be > > > told to discard the message. A reconnect doesn't address this issue. > > > > > I don't think there's a way to say that today. The RDS header flags are > > congestion-bitmap, ack-required, retransmitted and the extension-header > > bit. The only error a receiver can signal to its peer is to drop the > > connection. > > > > Not exactly true. > There's already code for the RDMA_CM_EVENT_REJECTED case to downgrade > protocol version. > > The RDS code can be changed. The RDS protocol can be extended. > A receiver could be made to tell a sender to drop a message, > if we'd consider that beneficial. > > But in this case, since the message itself violates the "unwritten rules" > of the RDS protocol, I'd say just dropping the message would be been > a fine choice. > > Dropping the connection however, doesn't do anything. > It just asks the sender to send the same bogus message again. > > > A per-message reject would be a protocol extension that both ends have to > > implement. But that would be net-next material, and it couldn't help > > against the only peers that actually send these. I'd be happy to review it > > if someone wants to take it on, but I don't think it should hold up a stable > > fix for a data disclosure. > > > > Again, we don't need to do that. > Dropping the message would have been a fine choice here. I think dropping just the offending message, and skipping the rest of its fragments by sequence, would be a reasonable refinement for net-next. And it would make sense to treat the header-mismatch exit the same way at the same time. I'd be happy to review patches for those. The landed fix does refuse to deliver the message though. The conn drop is the same policy the other exits in that function use too, so it's the right solution for stable. Patches welcome on the other points though. Thanks! Allison > > Thanks, > > Gerd > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [rds-devel] [External] : Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-19 22:44 ` Allison Henderson @ 2026-10-19 23:31 ` Gerd Rausch 0 siblings, 0 replies; 9+ messages in thread From: Gerd Rausch @ 2026-10-19 23:31 UTC (permalink / raw) To: Allison Henderson Cc: sungbyeongchan, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Andy Grover, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, rds-devel@oss.oracle.com, linux-kernel@vger.kernel.org Hi Allison, > On Oct 19, 2026, at 15:44, Allison Henderson <achender@kernel.org> wrote: > On Sun, 2026-10-18 at 18:32 +0000, Gerd Rausch wrote: >> >> Wait. This patch was created for a hypothetical case, no? >> Based on analysis of "Assisted-by: LLM". > Per Documents/process/coding-assistants.rst it means an LLM contributed in > some way, but sungbyeongchan patch had a reproducer and Shubham validated > it under KMSAN > I saw there was "a reproducer", but it is hard to tell what that thing did. I didn't see any source-code for that reproducer. RDS is designed to keep messages in "cp_retrans" unitl they're acknowledged by the peer. If the connection goes down, unacknowledged messages are sent again. It's the fundamental working principle of RDS. What reproducer would change this behavior? >> >> This patch does *not* refuse to deliver the bogus message. >> That would have been a fine choice. >> >> This patch just drops the underlying connection, in the hopes >> that when this message gets sent again, it'll somehow be different. > The short fragment is never linked, and the half-built inc is freed when the > connection shuts down, so it doesn't reach the socket. > Of course the message doesn't reach the socket. The backend connection is dropped via rds_ib_conn_error() -> rds_conn_drop(). The message remains in "cp_retrans", and gets sent again. It's the same message. Unless there's a transport error (that CRC-32 didn't catch), or some other non-deterministic behavior, the message will look exactly the same. So the exact same conditional will trigger again. And again. And again. >>> A per-message reject would be a protocol extension that both ends have to >>> implement. But that would be net-next material, and it couldn't help >>> against the only peers that actually send these. I'd be happy to review it >>> if someone wants to take it on, but I don't think it should hold up a stable >>> fix for a data disclosure. >>> >> >> Again, we don't need to do that. >> Dropping the message would have been a fine choice here. > > I think dropping just the offending message, and skipping the rest > of its fragments by sequence, would be a reasonable refinement for > net-next. And it would make sense to treat the header-mismatch exit > the same way at the same time. I'd be happy to review patches for those. > Why add a wrong fix to "net" first, to then fix it in "net-next"? Dropping an RDS connection because there was bogus payload is as useful as a compiler closing & reloading a file again, because there was a syntax error. The file won't look any different when you reload it. The message that RDS sends again, won't look any different either just because the backend connection was closed and then re-established. > The landed fix does refuse to deliver the message though. The conn drop is > the same policy the other exits in that function use too, so it's the right > solution for stable. Patches welcome on the other points though. I guess we can agree to disagree here. Thanks, Gerd ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net] RDS/IB: validate receive completion payload length 2026-10-06 20:52 [PATCH net] RDS/IB: validate receive completion payload length sungbyeongchan 2026-10-06 20:55 ` netdev-bot+sinfo 2026-10-07 1:13 ` Allison Henderson @ 2026-10-09 11:52 ` netdev-bot+sashiko 2 siblings, 0 replies; 9+ messages in thread From: netdev-bot+sashiko @ 2026-10-09 11:52 UTC (permalink / raw) To: tjdqudcks0424 Cc: achender, davem, edumazet, kuba, pabeni, horms, andy.grover, netdev, linux-rdma, rds-devel, linux-kernel Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider. Critical: 0 · High: 1 · Medium: 1 · Low: 1 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [High] The new length check can be bypassed, so the stale/uninitialized receive-fragment disclosure that this commit claims to close can still… - [Medium] When the new length check in rds_ib_process_recv() (net/rds/ib_recv.c:952-959) rejects a fragment, it jumps to `done` and… - [Low] The commit message understates the impact. -- RDS/IB: validate receive completion payload length This patch adds a check to rds_ib_process_recv(). The payload length reported by the receive completion must match the expected length of the current fragment, min(i_recv_data_rem, RDS_FRAG_SIZE). On mismatch the connection is dropped and reconnected, and the receive fragment is not attached to the incoming message. > An RDS/RDMA peer can declare a fragment length larger than the payload > reported by the receive completion. The receive path attaches the recycled > receive fragment without validating those lengths, allowing recvmsg() to > return stale bytes beyond the actual payload. [Severity: Low] Is "recycled receive fragment" the full picture here? When ic->i_cache_frags is empty, rds_ib_refill_one_frag() allocates a new page: net/rds/ib_recv.c:rds_ib_refill_one_frag() { ... ret = rds_page_remainder_alloc(&frag->f_sg, RDS_FRAG_SIZE, page_mask); ... } page_mask is either GFP_HIGHUSER or the caller's gfp. rds_page_remainder_alloc() then calls alloc_page() without __GFP_ZERO: net/rds/page.c:rds_page_remainder_alloc() { ... if (bytes >= PAGE_SIZE) { page = alloc_page(gfp); ... } On a fresh frag, the bytes after a short payload would be uninitialized kernel page contents, not only tails from earlier RDS messages. The code change covers this case too. Could the commit message also describe it as a kernel memory disclosure? > diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c > index bd6cb3ffaa571..0daddb108c8a7 100644 > --- a/net/rds/ib_recv.c > +++ b/net/rds/ib_recv.c > @@ -949,6 +949,15 @@ static void rds_ib_process_recv(struct rds_connection *conn, > } > } > > + if (data_len != min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)) { [Severity: High] Can an RDMA write with immediate get past this check? rds_ib_recv_cqe_handler() passes every successful completion to rds_ib_process_recv() without checking wc->opcode: net/rds/ib_recv.c:rds_ib_recv_cqe_handler() { ... if (wc->status == IB_WC_SUCCESS) { rds_ib_process_recv(conn, recv, wc->byte_len, state); ... } A write with immediate uses up the next receive WQE but does not write to its scatter list (ic->i_recv_hdrs[slot] and recv->r_frag). For IB_WC_RECV_RDMA_WITH_IMM, byte_len is the RDMA write length. In rxe, for example: drivers/infiniband/sw/rxe/rxe_resp.c:do_complete() { ... wc->byte_len = (pkt->mask & RXE_IMMDT_MASK && pkt->mask & RXE_WRITE_MASK) ? qp->resp.length : wqe->dma.length - wqe->dma.resid; ... } The header buffer for a ring slot is never cleared between uses. It still holds the last normal header received into that slot, and that header's checksum still verifies. recv->r_frag is either a recycled frag from the cache or a fresh alloc_page() page. rds_ib_post_reg_frmr() registers RDS MRs with IB_ACCESS_REMOTE_WRITE. A peer holding an rkey from a local RDS user could then do this: 1. send a normal message into a slot with h_len=4096, a bound dport, and RDS_FLAG_RETRANSMITTED clear 2. when that slot comes around again, issue a write with immediate of sizeof(struct rds_header) + 4096 bytes to a remote-writable MR The new check sees data_len == min(i_recv_data_rem, RDS_FRAG_SIZE) and passes, so the unwritten frag is attached. rds_recv_incoming() only drops old sequence numbers when RDS_FLAG_RETRANSMITTED is set: net/rds/recv.c:rds_recv_incoming() { ... if (be64_to_cpu(inc->i_hdr.h_sequence) < cp->cp_next_rx_seq && (inc->i_hdr.h_flags & RDS_FLAG_RETRANSMITTED)) { ... } rds_ib_inc_copy_to_user() would then copy h_len bytes of stale or uninitialized frag data to userspace. Should completions whose opcode is not IB_WC_RECV be rejected before the receive buffers are parsed or byte_len is trusted? > + rds_ib_conn_error(conn, > + "incoming fragment payload length %u, expected %u; " > + "disconnecting and reconnecting\n", > + data_len, > + min_t(u32, ic->i_recv_data_rem, RDS_FRAG_SIZE)); > + goto done; > + } [Severity: Medium] Does this goto done leave the partial message in place for later fragments to complete? ic->i_ibinc stays set (it was just installed if this fragment started the message), and ic->i_recv_data_rem is not reduced. rds_ib_conn_error() ends up in rds_conn_path_drop(). That function only sets RDS_CONN_ERROR and queues the shutdown work: net/rds/connection.c:rds_conn_path_drop() { ... atomic_set(&cp->cp_state, RDS_CONN_ERROR); ... queue_work(cp->cp_wq, &cp->cp_down_w); ... } In the meantime poll_rcq() keeps calling rds_ib_recv_cqe_handler() for the rest of the batch. Later tasklet runs do the same until shutdown sets i_cq_quiesce. A later fragment with the same h_sequence, h_len and ports, and the expected length, passes both the header comparison and the new check. For example, with h_len=8192 and these completions: A: 4096 bytes -> attached, rem = 4096 B: 16 bytes -> rejected here, rem still 4096 C: 4096 bytes -> attached, rem = 0 The message is delivered as A+C, with C's payload where B's belongs. rds_recv_incoming() does not check the connection error state. The message is queued to the socket and acked through state->ack_next, and cp_next_rx_seq advances. A later retransmission flagged RDS_FLAG_RETRANSMITTED would then be dropped as old. This seems to contradict the commit message: "With this change, the malformed message was not delivered" The existing fragment header mismatch path has the same weakness, and this patch adds a second rejection path that shares it. Could the in-progress inc be dropped here instead? That would mean calling rds_inc_put(&ic->i_ibinc->ii_inc) and clearing ic->i_ibinc and ic->i_recv_data_rem. Another option is to stop reassembly once the connection is in error. > list_add_tail(&recv->r_frag->f_item, &ibinc->ii_frags); > recv->r_frag = NULL; > -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261006205204.1322102-1-tjdqudcks0424%40naver.com ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-19 23:32 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-06 20:52 [PATCH net] RDS/IB: validate receive completion payload length sungbyeongchan 2026-10-06 20:55 ` netdev-bot+sinfo 2026-10-07 1:13 ` Allison Henderson 2026-10-16 20:18 ` [rds-devel] [External] : " Gerd Rausch 2026-10-18 5:38 ` Allison Henderson 2026-10-18 18:32 ` Gerd Rausch 2026-10-19 22:44 ` Allison Henderson 2026-10-19 23:31 ` Gerd Rausch 2026-10-09 11:52 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox