[PATCH 8/8] SUNRPC: fold xs_sock_process_cmsg() into its only caller
From: Chuck Lever <cel@kernel.org>
Date: 2026-08-05 18:31:17
Also in:
linux-nfs
Subsystem:
kernel nfsd, sunrpc, and lockd servers, networking [general], nfs, sunrpc, and lockd clients, the rest · Maintainers:
Chuck Lever, Jeff Layton, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Trond Myklebust, Anna Schumaker, Linus Torvalds
xs_sock_process_cmsg() switches on the TLS record type, and every arm but TLS_RECORD_TYPE_ALERT returns the -EAGAIN its caller passed in. The DATA arm clears MSG_EOR in the caller's msghdr, but xs_sock_recvmsg() has already cleared that flag before the call. Deriving the record type a second time inside the helper also fires trace_tls_contenttype() twice for every alert. Move the alert handling into xs_sock_recv_cmsg() and delete the helper. Every other record type still returns -EAGAIN. The DATA arm's account of MSG_EOR moves to xs_sock_recvmsg(), where the flag is cleared. Signed-off-by: Chuck Lever <cel@kernel.org> --- net/sunrpc/xprtsock.c | 85 ++++++++++++++++++--------------------------------- 1 file changed, 30 insertions(+), 55 deletions(-)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 5527f7f8a185..38dd75a23af7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c@@ -356,45 +356,6 @@ xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp) return want; } -static int -xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, - unsigned int *msg_flags, struct cmsghdr *cmsg, int ret) -{ - u8 content_type = tls_get_record_type(sock->sk, cmsg); - u8 level, description; - - switch (content_type) { - case 0: - break; - case TLS_RECORD_TYPE_DATA: - /* TLS sets EOR at the end of each application data - * record, even though there might be more frames - * waiting to be decrypted. - */ - *msg_flags &= ~MSG_EOR; - break; - case TLS_RECORD_TYPE_ALERT: - tls_alert_recv(sock->sk, msg, &level, &description); - /* RFC 8446 Section 6: every alert but a closure alert is - * an error alert, whatever the legacy AlertLevel octet - * says. - */ - switch (description) { - case TLS_ALERT_DESC_CLOSE_NOTIFY: - case TLS_ALERT_DESC_USER_CANCELED: - ret = -EAGAIN; - break; - default: - ret = -EACCES; - } - break; - default: - /* discard this record type */ - ret = -EAGAIN; - } - return ret; -} - static int xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags) {
@@ -412,6 +373,7 @@ xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags) .msg_control = &u, .msg_controllen = sizeof(u), }; + u8 level, description; int ret; iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
@@ -421,23 +383,32 @@ xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags) * kTLS filled in u.cmsg. */ if (ret >= 0 && msg.msg_controllen < sizeof(u)) { - if (tls_get_record_type(sock->sk, &u.cmsg) == - TLS_RECORD_TYPE_ALERT) { - /* RFC 8446 Section 5.1 requires a record with an - * Alert type to carry exactly one message. An alert - * is two octets. tls_alert_recv() reads both without - * checking the length. alert_kvec caps the count at - * two, so a longer record fills it as well. kTLS - * sets MSG_EOR only once the record has been - * drained. - */ - if (ret != sizeof(alert) || - !(msg.msg_flags & MSG_EOR)) - return -EACCES; - iov_iter_revert(&msg.msg_iter, ret); + if (tls_get_record_type(sock->sk, &u.cmsg) != + TLS_RECORD_TYPE_ALERT) + return -EAGAIN; + /* RFC 8446 Section 5.1: a record with an Alert type carries + * exactly one message, and an alert is two octets. + * tls_alert_recv() reads both without checking the length. + * alert_kvec caps the count at two, so a longer record + * fills it as well. kTLS sets MSG_EOR only once the + * record has been drained. + */ + if (ret != sizeof(alert) || !(msg.msg_flags & MSG_EOR)) + return -EACCES; + iov_iter_revert(&msg.msg_iter, ret); + tls_alert_recv(sock->sk, &msg, &level, &description); + /* RFC 8446 Section 6: every alert but a closure alert is + * an error alert, whatever the legacy AlertLevel octet + * says. + */ + switch (description) { + case TLS_ALERT_DESC_CLOSE_NOTIFY: + case TLS_ALERT_DESC_USER_CANCELED: + ret = -EAGAIN; + break; + default: + ret = -EACCES; } - ret = xs_sock_process_cmsg(sock, &msg, msg_flags, &u.cmsg, - -EAGAIN); } return ret; }
@@ -451,6 +422,10 @@ xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek) ret = sock_recvmsg(sock, msg, flags); /* Handle TLS inband control message lazily */ if (msg->msg_flags & MSG_CTRUNC) { + /* TLS sets EOR at the end of each application data + * record, even though there might be more frames + * waiting to be decrypted. + */ msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR); if (ret == 0 || ret == -EIO) ret = xs_sock_recv_cmsg(sock, &msg->msg_flags, flags);
--
2.54.0