[RFC PATCH 2/4] tls: Implement read_sock_cmsg for kTLS software path

Chuck Lever <[email protected]>
Newsgroups dev.linux.lists.kernel-tls-handshake
Message-ID <[email protected]>
From: Chuck Lever <[email protected]>

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 slower sock_recvmsg() API to receive control messages
via CMSG.

Implement a more efficient API based on the new read_sock_cmsg()
method for these consumers.

Signed-off-by: Chuck Lever <[email protected]>
---
 net/tls/tls.h      |  3 +++
 net/tls/tls_main.c |  2 ++
 net/tls/tls_sw.c   | 33 ++++++++++++++++++++++++++++-----
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/net/tls/tls.h b/net/tls/tls.h
index 2f86baeb71fc..2e1581b6ca25 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_cmsg(struct sock *sk, read_descriptor_t *desc,
+			   sk_read_actor_t read_actor,
+			   sk_read_cmsg_actor_t cmsg_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 56ce0bc8317b..40163d7baab4 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -946,11 +946,13 @@ 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_cmsg	= tls_sw_read_sock_cmsg;
 
 	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_cmsg	= tls_sw_read_sock_cmsg;
 
 #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 9937d4c810f2..e45352b167c4 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -2325,8 +2325,9 @@ ssize_t tls_sw_splice_read(struct socket *sock,  loff_t *ppos,
 	goto splice_read_end;
 }
 
-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_cmsg_actor_t cmsg_actor)
 {
 	struct tls_context *tls_ctx = tls_get_ctx(sk);
 	struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -2387,10 +2388,19 @@ 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 */
 		if (tlm->control != TLS_RECORD_TYPE_DATA) {
-			err = -EINVAL;
-			goto read_sock_requeue;
+			if (!cmsg_actor) {
+				err = -EINVAL;
+				goto read_sock_requeue;
+			}
+			err = cmsg_actor(desc, skb, rxm->offset,
+					 rxm->full_len, tlm->control);
+			if (err < 0)
+				goto read_sock_requeue;
+			consume_skb(skb);
+			if (!desc->count)
+				skb = NULL;
+			continue;
 		}
 
 		used = read_actor(desc, skb, rxm->offset, rxm->full_len);
@@ -2421,6 +2431,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_cmsg(struct sock *sk, read_descriptor_t *desc,
+			   sk_read_actor_t read_actor,
+			   sk_read_cmsg_actor_t cmsg_actor)
+{
+	return __tls_sw_read_sock(sk, desc, read_actor, cmsg_actor);
+}
+
 bool tls_sw_sock_is_readable(struct sock *sk)
 {
 	struct tls_context *tls_ctx = tls_get_ctx(sk);
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.