* [PATCH net] net: rds: check cmsg_len before reading rds_rdma_args in size pass
@ 2026-06-14 13:07 Michael Bommarito
2026-06-15 4:54 ` Allison Henderson
0 siblings, 1 reply; 2+ messages in thread
From: Michael Bommarito @ 2026-06-14 13:07 UTC (permalink / raw)
To: Allison Henderson, David S . Miller, Jakub Kicinski, Paolo Abeni,
Eric Dumazet
Cc: Simon Horman, netdev, linux-rdma, rds-devel, linux-kernel
For RDS_CMSG_RDMA_ARGS, rds_rm_size() calls rds_rdma_extra_size() after
only CMSG_OK(), without checking that cmsg_len covers struct
rds_rdma_args. rds_rdma_extra_size() reads args->local_vec_addr and
args->nr_local, so a short control message reads past the copied control
buffer. The value bounds an allocation count, so this is an
out-of-bounds read in the kernel, not a leak to user space, and an
unprivileged AF_RDS socket can trigger it with one short cmsg.
The two later RDS_RDMA passes (rds_cmsg_rdma_args() and the rdma-bytes
loop in rds_sendmsg()) already reject cmsg_len < CMSG_LEN(sizeof(struct
rds_rdma_args)); only this size pass does not. Reject it the same way.
Reproduced under KASAN on QEMU via a KUnit driving the real
rds_rm_size(); the out-of-bounds read is gone after this change.
Fixes: ff87e97a9d70 ("RDS: make m_rdma_op a member of rds_message")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
A short RDS_CMSG_RDMA_ARGS placed at a page boundary makes
rds_rdma_extra_size() read the args fields past the allocation:
BUG: KASAN: slab-out-of-bounds in rds_rdma_extra_size
an 8-byte read. On stock it faults; patched it returns -EINVAL with no
report. Controls (well-formed args; a short cmsg with args still in
bounds) drive the same pass cleanly on both trees.
No in-tree selftest exercises rds_rm_size(); I can send the KUnit suite
as a separate net-next patch if wanted, kept out so the fix is not held.
net/rds/send.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/rds/send.c b/net/rds/send.c
index d8b14ff9d366b..6ca3192b1d8af 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -967,6 +967,8 @@ static int rds_rm_size(struct msghdr *msg, int num_sgs,
switch (cmsg->cmsg_type) {
case RDS_CMSG_RDMA_ARGS:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args)))
+ return -EINVAL;
if (vct->indx >= vct->len) {
vct->len += vct->incr;
tmp_iov =
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH net] net: rds: check cmsg_len before reading rds_rdma_args in size pass
2026-06-14 13:07 [PATCH net] net: rds: check cmsg_len before reading rds_rdma_args in size pass Michael Bommarito
@ 2026-06-15 4:54 ` Allison Henderson
0 siblings, 0 replies; 2+ messages in thread
From: Allison Henderson @ 2026-06-15 4:54 UTC (permalink / raw)
To: Michael Bommarito, David S . Miller, Jakub Kicinski, Paolo Abeni,
Eric Dumazet
Cc: Simon Horman, netdev, linux-rdma, rds-devel, linux-kernel
On Sun, 2026-06-14 at 09:07 -0400, Michael Bommarito wrote:
Hi Michael,
Thanks for looking at this. A few comments below:
> For RDS_CMSG_RDMA_ARGS, rds_rm_size() calls rds_rdma_extra_size() after
> only CMSG_OK(), without checking that cmsg_len covers struct
> rds_rdma_args. rds_rdma_extra_size() reads args->local_vec_addr and
> args->nr_local, so a short control message reads past the copied control
> buffer. The value bounds an allocation count, so this is an
> out-of-bounds read in the kernel, not a leak to user space, and an
> unprivileged AF_RDS socket can trigger it with one short cmsg.
>
> The two later RDS_RDMA passes (rds_cmsg_rdma_args() and the rdma-bytes
> loop in rds_sendmsg())
>
I puzzled over this line for a bit since rds_sendmsg doesnt call
rds_cmsg_rdma_args directly. I think you meant:
"(rds_rdma_bytes() in rds_sendmsg(), and rds_cmsg_rdma_args() in rds_cmsg_send())"
?
Also, note that rds_rdma_bytes() runs before rds_rm_size(), not later.
That ordering matters as noted below:
> already reject cmsg_len < CMSG_LEN(sizeof(struct
> rds_rdma_args)); only this size pass does not. Reject it the same way.
>
> Reproduced under KASAN on QEMU via a KUnit driving the real
> rds_rm_size(); the out-of-bounds read is gone after this change.
>
> Fixes: ff87e97a9d70 ("RDS: make m_rdma_op a member of rds_message")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> ---
> A short RDS_CMSG_RDMA_ARGS placed at a page boundary makes
> rds_rdma_extra_size() read the args fields past the allocation:
>
> BUG: KASAN: slab-out-of-bounds in rds_rdma_extra_size
>
> an 8-byte read. On stock it faults; patched it returns -EINVAL with no
> report. Controls (well-formed args; a short cmsg with args still in
> bounds) drive the same pass cleanly on both trees.
>
> No in-tree selftest exercises rds_rm_size(); I can send the KUnit suite
> as a separate net-next patch if wanted, kept out so the fix is not held.
>
> net/rds/send.c | 2 ++
> 1 file changed, 2 insertions(+)
The code change itself looks ok, but it's not really a bug fix.
rds_rm_size() is only called from once place: line 1290 in rds_sendmsg().
Here, cmsg_len is already verified by rds_rdma_bytes(), which performs the
same cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args)) check for
RDS_CMSG_RDMA_ARGS before rds_rm_size() ever runs.
ret = rds_rdma_bytes(msg, &rdma_payload_len); <------------ cmsg sanity checking done here
if (ret)
goto out;
if (max_t(size_t, payload_len, rdma_payload_len) > RDS_MAX_MSG_SIZE) {
ret = -EMSGSIZE;
goto out;
}
if (payload_len > rds_sk_sndbuf(rs)) {
ret = -EMSGSIZE;
goto out;
}
if (zcopy) {
if (rs->rs_transport->t_type != RDS_TRANS_TCP) {
ret = -EOPNOTSUPP;
goto out;
}
num_sgs = iov_iter_npages(&msg->msg_iter, INT_MAX);
}
/* size of rm including all sgs */
ret = rds_rm_size(msg, num_sgs, &vct); <-------------- rds_rm_size only called here
if (ret < 0)
goto out;
A KUnit test directly calling rds_rm_size() might run across an OOB if it
shortcuts this pre-check, but this isnt something a user could reach through
sendmesg since the rds_rdma_bytes() check would reject it first.
The patch is still a reasonable hardening fix, it just shouldn't be carrying
a fixes tag or targeting net. Please re-target this patch for net-next instead
of net, and drop the fixes tag. No need to cc stable. We should also clarify
the commit message as noted above, as well as remove the line about the AF_RDS
socket. Other than that, I think it's a good change.
Thanks for working on this!
Allison
>
> diff --git a/net/rds/send.c b/net/rds/send.c
> index d8b14ff9d366b..6ca3192b1d8af 100644
> --- a/net/rds/send.c
> +++ b/net/rds/send.c
> @@ -967,6 +967,8 @@ static int rds_rm_size(struct msghdr *msg, int num_sgs,
>
> switch (cmsg->cmsg_type) {
> case RDS_CMSG_RDMA_ARGS:
> + if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args)))
> + return -EINVAL;
> if (vct->indx >= vct->len) {
> vct->len += vct->incr;
> tmp_iov =
>
> base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-15 4:54 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-14 13:07 [PATCH net] net: rds: check cmsg_len before reading rds_rdma_args in size pass Michael Bommarito
2026-06-15 4:54 ` Allison Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox