[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