rxrpc: Fix sendmsg length

rxrpc_send_data() is given two data lengths (len and msg->msg_iter.count)
and is inconsistent about how it uses them.  Fix this by using len in
preference to msg->msg_iter.count.  Also limit the amount copied to either
len or msg->msg_iter.count, whichever is smaller.

Note that, currently, all the callers have len and msg->msg_iter.count the
same and so the problem won't occur.  This is a prerequisite for another
patch that fixes the handling of encryption errors.

Fixes: 382d7974de ("RxRPC: Use iov_iter_count() in rxrpc_send_data() instead of the len argument")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20261006133011.531806-8-dhowells@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
David Howells 2026-10-06 14:29:59 +01:00 committed by Paolo Abeni
parent 7f15923909
commit ef369cacbd

View File

@ -374,9 +374,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
ret = -EMSGSIZE;
if (call->tx_total_len != -1) {
if (len - copied > call->tx_total_len)
if (len > call->tx_total_len)
goto maybe_error;
if (!more && len - copied != call->tx_total_len)
if (!more && len != call->tx_total_len)
goto maybe_error;
}
@ -402,7 +402,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
* the security header is going to be in the padded
* region (enc blocksize), but the trailer is not.
*/
remain = more ? INT_MAX : msg_data_left(msg);
remain = more ? INT_MAX : len;
txb = call->conn->security->alloc_txbuf(call, remain, sk->sk_allocation);
if (!txb) {
ret = -ENOMEM;
@ -416,8 +416,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
_debug("append");
/* append next segment of data to the current buffer */
if (msg_data_left(msg) > 0) {
size_t copy = umin(txb->space, msg_data_left(msg));
if (len > 0) {
size_t copy = min3(txb->space, len, msg_data_left(msg));
_debug("add %zu", copy);
if (!copy_from_iter_full(txb->data + txb->offset,
@ -428,6 +428,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
txb->len += copy;
txb->offset += copy;
copied += copy;
len -= copy;
if (call->tx_total_len != -1)
call->tx_total_len -= copy;
}
@ -439,8 +440,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
/* add the packet to the send queue if it's now full */
if (!txb->space ||
(msg_data_left(msg) == 0 && !more)) {
if (msg_data_left(msg) == 0 && !more)
(len == 0 && !more)) {
if (len == 0 && !more)
txb->flags |= RXRPC_LAST_PACKET;
ret = call->security->secure_packet(call, txb);
@ -449,7 +450,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
rxrpc_queue_packet(rx, call, txb, notify_end_tx);
call->tx_pending = NULL;
}
} while (msg_data_left(msg) > 0);
} while (len > 0 && msg_data_left(msg) > 0);
success:
ret = copied;