[PATCH net-next v2 3/6] tls: Implement read_sock_rectype for kTLS software path
From: Chuck Lever <cel@kernel.org>
Date: 2026-07-20 14:28:18
Also in:
linux-kselftest, linux-nfs
Subsystem:
networking [general], networking [tls], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, John Fastabend, Sabrina Dubroca, Linus Torvalds
From: Chuck Lever <redacted> tls_sw_read_sock() rejects non-data records (alerts, handshake messages) with -EINVAL. Kernel consumers that need TLS alert delivery, such as NFSD, NFS client, and NVMe target, must fall back to the sock_recvmsg() API to receive control messages via CMSG. Implement the new read_sock_rectype() method for these consumers, delivering non-data records to a callback through the kTLS software receive path. Signed-off-by: Chuck Lever <redacted> --- net/tls/tls.h | 3 +++ net/tls/tls_main.c | 5 +++++ net/tls/tls_sw.c | 41 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/net/tls/tls.h b/net/tls/tls.h
index 60a37bdaaa25..c21d2a985e13 100644
--- a/net/tls/tls.h
+++ b/net/tls/tls.h@@ -168,6 +168,9 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, size_t len, unsigned int flags); int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, sk_read_actor_t read_actor); +int tls_sw_read_sock_rectype(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t read_actor, + sk_read_rectype_actor_t rectype_actor); int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); void tls_device_splice_eof(struct socket *sock);
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 8c588cdab733..4963e0caf6d5 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c@@ -949,12 +949,17 @@ static void build_proto_ops(struct proto_ops ops[TLS_NUM_CONFIG][TLS_NUM_CONFIG] ops[TLS_BASE][TLS_SW ].splice_read = tls_sw_splice_read; ops[TLS_BASE][TLS_SW ].poll = tls_sk_poll; ops[TLS_BASE][TLS_SW ].read_sock = tls_sw_read_sock; + ops[TLS_BASE][TLS_SW ].read_sock_rectype = tls_sw_read_sock_rectype; ops[TLS_SW ][TLS_SW ] = ops[TLS_SW ][TLS_BASE]; ops[TLS_SW ][TLS_SW ].splice_read = tls_sw_splice_read; ops[TLS_SW ][TLS_SW ].poll = tls_sk_poll; ops[TLS_SW ][TLS_SW ].read_sock = tls_sw_read_sock; + ops[TLS_SW ][TLS_SW ].read_sock_rectype = tls_sw_read_sock_rectype; + /* TLS_HW (device offload) RX entries inherit + * read_sock{,_rectype} from SW via the struct copies below. + */ #ifdef CONFIG_TLS_DEVICE ops[TLS_HW ][TLS_BASE] = ops[TLS_BASE][TLS_BASE];
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 087950ca639c..af347b5b17fa 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c@@ -2054,8 +2054,9 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, */ #define TLS_RX_NODATA_LIMIT 16 -int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, - sk_read_actor_t read_actor) +static int __tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t read_actor, + sk_read_rectype_actor_t rectype_actor) { struct tls_context *tls_ctx = tls_get_ctx(sk); struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -2115,10 +2116,27 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, tls_rx_rec_done(ctx); } - /* read_sock does not support reading control messages */ + /* Control records (alerts, handshake) reach a consumer + * only through rectype_actor; without one, read_sock + * rejects them. + */ if (tlm->control != TLS_RECORD_TYPE_DATA) { - err = -EINVAL; - goto read_sock_requeue; + if (!rectype_actor) { + err = -EINVAL; + goto read_sock_requeue; + } + err = rectype_actor(desc, skb, rxm->offset, + rxm->full_len, + tlm->control); + if (err < 0) + goto read_sock_requeue; + err = 0; + /* rectype_actor consumes the whole record; no partial path */ + consume_skb(skb); + skb = NULL; + if (++nodata_count >= TLS_RX_NODATA_LIMIT) + break; + continue; } /* An empty data record (legal in TLS 1.3) gives a zero
@@ -2164,6 +2182,19 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, goto read_sock_end; } +int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t read_actor) +{ + return __tls_sw_read_sock(sk, desc, read_actor, NULL); +} + +int tls_sw_read_sock_rectype(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t read_actor, + sk_read_rectype_actor_t rectype_actor) +{ + return __tls_sw_read_sock(sk, desc, read_actor, rectype_actor); +} + bool tls_sw_sock_is_readable(struct sock *sk) { struct tls_context *tls_ctx = tls_get_ctx(sk);
--
2.54.0