]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: rds: check cmsg_len before reading rds_rdma_args in size pass
authorMichael Bommarito <michael.bommarito@gmail.com>
Wed, 17 Jun 2026 02:31:46 +0000 (22:31 -0400)
committerJakub Kicinski <kuba@kernel.org>
Fri, 19 Jun 2026 01:25:28 +0000 (18:25 -0700)
rds_rm_size() handles RDS_CMSG_RDMA_ARGS after only CMSG_OK() and then
calls rds_rdma_extra_size(), which reads args->local_vec_addr and
args->nr_local without first checking that cmsg_len covers struct
rds_rdma_args. The other two RDS_CMSG_RDMA_ARGS consumers already guard
this: rds_rdma_bytes() in rds_sendmsg() and rds_cmsg_rdma_args() in
rds_cmsg_send() both reject cmsg_len < CMSG_LEN(sizeof(struct
rds_rdma_args)). Add the same check to rds_rm_size() so all three RDMA
args passes are consistent.

This is a consistency and hardening change with no behavioral effect for
well-formed senders and no reachable bug today: rds_rdma_bytes() runs
before rds_rm_size() in rds_sendmsg() and already rejects a short
RDS_CMSG_RDMA_ARGS, so the size pass is not reached with an undersized
cmsg. But rds_rm_size() reads the args independently of that earlier
pass, and nothing in rds_rm_size() itself records or enforces the
precondition, so a reader or a future refactor of the size pass cannot
tell the cmsg has already been length-checked. Applying the same
cmsg_len guard in all three RDS_CMSG_RDMA_ARGS consumers keeps that
invariant local to each and robust to reordering.

Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20260617023146.2780077-1-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/rds/send.c

index e5d58c29aabea3d434ff12d617fcdd642140bd2e..68be1bf0e0adf96a5eabe2df7a397afaf0d88d7d 100644 (file)
@@ -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 =