]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
tls: Re-present partially-consumed records in tls_sw_read_sock()
authorChuck Lever <chuck.lever@oracle.com>
Thu, 4 Jun 2026 17:48:25 +0000 (13:48 -0400)
committerJakub Kicinski <kuba@kernel.org>
Tue, 9 Jun 2026 03:10:21 +0000 (20:10 -0700)
The tls_sw_read_sock() loop releases the current skb whether
read_actor() consumed the full record or only a prefix. When
the actor takes only part of the record and leaves desc->count
non-zero, the remainder is lost: skb is neither requeued nor
freed, and the next iteration overwrites it during dequeue or
tls_rx_rec_wait().

No mainline consumer reaches this path today. The only
in-tree TLS read_sock user is nvme/tcp, whose actor
nvme_tcp_recv_skb() loops until the input length is exhausted
and returns either the full length or a negative error.

The path becomes reachable with the upcoming NFSD svcsock
receive built on read_sock_cmsg. Its data actor,
svc_tcp_recv_actor(), parses an RPC fragment stream
incrementally and returns at fragment boundaries. When a TLS
record carries the tail of one RPC fragment plus the head of
the next, the actor returns fewer bytes than offered while
leaving desc->count non-zero, and without re-presentation the
trailing fragment header vanishes.

__tcp_read_sock() handles the equivalent case for plain TCP
by leaving the unread bytes available for the next iteration
to re-present, via sequence-number re-lookup. Adopt the same
loop-level behavior: when read_actor() consumes only part of
the record, update rxm->offset and rxm->full_len and requeue
the skb to the head of rx_list so the next iteration
re-presents the unread bytes. Switch the open-ended for-loop
to "while (desc->count)" so the partial- and full-consume
arms share a single exit check and read_actor() is not
re-invoked once desc->count is exhausted.

Cc: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20260604-tls-read-sock-v12-2-b114efa6e3e2@oracle.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/tls/tls_sw.c

index 8e4e57721335498542da5af645aaa385a40d998a..fd8d3c97936848ba07a8fec5ad8218c58d0700c1 100644 (file)
@@ -2383,7 +2383,7 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
                goto read_sock_end;
 
        decrypted = 0;
-       for (;;) {
+       while (desc->count) {
                if (!skb_queue_empty(&ctx->rx_list)) {
                        skb = __skb_dequeue(&ctx->rx_list);
                        rxm = strp_msg(skb);
@@ -2430,12 +2430,9 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
                if (used < rxm->full_len) {
                        rxm->offset += used;
                        rxm->full_len -= used;
-                       if (!desc->count)
-                               goto read_sock_requeue;
+                       __skb_queue_head(&ctx->rx_list, skb);
                } else {
                        consume_skb(skb);
-                       if (!desc->count)
-                               break;
                }
        }