git: 8908c590e365 - stable/13 - krpc: Fix NFS-over-TLS for KTLS1.3

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Tue, 31 May 2022 00:40:02 UTC
The branch stable/13 has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=8908c590e365584666532d59125fffd721b267d3

commit 8908c590e365584666532d59125fffd721b267d3
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2022-05-15 18:51:56 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2022-05-31 00:38:43 +0000

    krpc: Fix NFS-over-TLS for KTLS1.3
    
    When NFS-over-TLS uses KTLS1.3, the client can receive
    post-handshake handshake records.  These records can be
    safely thown away, but are not handled correctly via the
    rpctls_ct_handlerecord() upcall to the daemon.
    
    Commit 373511338d95 changed soreceive_generic() so that it
    will only return ENXIO for Alert records when MSG_TLSAPPDATA
    is specified.  As such, the post-handshake handshake
    records will be returned to the krpc.
    
    This patch modifies the krpc so that it will throw
    these records away, which seems sufficient to make
    NFS-over-TLS work with KTLS1.3.  This change has
    no effect on the use of KTLS1.2, since it does not
    generate post-handshake handshake records.
    
    (cherry picked from commit 0b4f2ab0e91307bd1fa6e884b0fccef9d10d5a2d)
---
 sys/rpc/clnt_vc.c | 21 +++++++++------------
 sys/rpc/svc_vc.c  | 12 ++++++------
 2 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c
index 7d22c670b017..8ad6746eb485 100644
--- a/sys/rpc/clnt_vc.c
+++ b/sys/rpc/clnt_vc.c
@@ -946,7 +946,7 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag)
 {
 	struct ct_data *ct = (struct ct_data *) arg;
 	struct uio uio;
-	struct mbuf *m, *m2, **ctrlp;
+	struct mbuf *m, *m2;
 	struct ct_request *cr;
 	int error, rcvflag, foundreq;
 	uint32_t xid_plus_direction[2], header;
@@ -994,13 +994,10 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag)
 		m2 = m = NULL;
 		rcvflag = MSG_DONTWAIT | MSG_SOCALLBCK;
 		if (ct->ct_sslrefno != 0 && (ct->ct_rcvstate &
-		    RPCRCVSTATE_NORMAL) != 0) {
+		    RPCRCVSTATE_NORMAL) != 0)
 			rcvflag |= MSG_TLSAPPDATA;
-			ctrlp = NULL;
-		} else
-			ctrlp = &m2;
 		SOCKBUF_UNLOCK(&so->so_rcv);
-		error = soreceive(so, NULL, &uio, &m, ctrlp, &rcvflag);
+		error = soreceive(so, NULL, &uio, &m, &m2, &rcvflag);
 		SOCKBUF_LOCK(&so->so_rcv);
 
 		if (error == EWOULDBLOCK) {
@@ -1025,8 +1022,8 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag)
 		}
 
 		/*
-		 * A return of ENXIO indicates that there is a
-		 * non-application data record at the head of the
+		 * A return of ENXIO indicates that there is an
+		 * alert record at the head of the
 		 * socket's receive queue, for TLS connections.
 		 * This record needs to be handled in userland
 		 * via an SSL_read() call, so do an upcall to the daemon.
@@ -1053,10 +1050,10 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag)
 			    cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) {
 				memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr));
 				/*
-				 * This should have been handled by
-				 * setting RPCRCVSTATE_UPCALLNEEDED in
-				 * ct_rcvstate but if not, all we can do
-				 * is toss it away.
+				 * TLS_RLTYPE_ALERT records should be handled
+				 * since soreceive() would have returned
+				 * ENXIO.  Just throw any other
+				 * non-TLS_RLTYPE_APP records away.
 				 */
 				if (tgr.tls_type != TLS_RLTYPE_APP) {
 					m_freem(m);
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index 77452d906594..eb63cb1da4e4 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -806,8 +806,8 @@ tryagain:
 		}
 
 		/*
-		 * A return of ENXIO indicates that there is a
-		 * non-application data record at the head of the
+		 * A return of ENXIO indicates that there is an
+		 * alert record at the head of the
 		 * socket's receive queue, for TLS connections.
 		 * This record needs to be handled in userland
 		 * via an SSL_read() call, so do an upcall to the daemon.
@@ -865,10 +865,10 @@ tryagain:
 			    cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) {
 				memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr));
 				/*
-				 * This should have been handled by
-				 * the rpctls_svc_handlerecord()
-				 * upcall.  If not, all we can do is
-				 * toss it away.
+				 * TLS_RLTYPE_ALERT records should be handled
+				 * since soreceive() would have returned
+				 * ENXIO.  Just throw any other
+				 * non-TLS_RLTYPE_APP records away.
 				 */
 				if (tgr.tls_type != TLS_RLTYPE_APP) {
 					m_freem(m);