git: 4be9c6f38e78 - main - clnt_rc.c: Fix the case where a TLS handshake fails

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Sat, 19 Jul 2025 00:41:50 UTC
The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=4be9c6f38e7859b8c913a75f7d900cd79ef6692a

commit 4be9c6f38e7859b8c913a75f7d900cd79ef6692a
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2025-07-19 00:39:08 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2025-07-19 00:39:08 +0000

    clnt_rc.c: Fix the case where a TLS handshake fails
    
    When a TLS handshake fails during a NFS-over-TLS
    mount attempt, the socket was left around because
    it needed to be dereferenced. The dereference was
    not happening in clnt_vc_destroy() because ct_closeit
    was not set to TRUE.
    
    This patch moves the code that sets ct_closeit to TRUE
    up to before the rpctls_connect() call, so that ct_closeit
    is set to TRUE if it fails and clnt_vc_destroy() will then
    dereference the socket.
    
    Reviewed by:    glebius
    Differential Revision:  https://reviews.freebsd.org/D51084
---
 sys/rpc/clnt_rc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/rpc/clnt_rc.c b/sys/rpc/clnt_rc.c
index 9e87af578885..44b63e38a8e6 100644
--- a/sys/rpc/clnt_rc.c
+++ b/sys/rpc/clnt_rc.c
@@ -198,6 +198,12 @@ clnt_reconnect_connect(CLIENT *cl)
 		newclient = clnt_vc_create(so,
 		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
 		    rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr);
+		/*
+		 * CLSET_FD_CLOSE must be done now, in case rpctls_connect()
+		 * fails just below.
+		 */
+		if (newclient != NULL)
+			CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0);
 		if (rc->rc_tls && newclient != NULL) {
 			CURVNET_SET(so->so_vnet);
 			stat = rpctls_connect(newclient, rc->rc_tlscertname, so,
@@ -236,7 +242,6 @@ clnt_reconnect_connect(CLIENT *cl)
 		goto out;
 	}
 
-	CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0);
 	CLNT_CONTROL(newclient, CLSET_CONNECT, &one);
 	CLNT_CONTROL(newclient, CLSET_TIMEOUT, &rc->rc_timeout);
 	CLNT_CONTROL(newclient, CLSET_RETRY_TIMEOUT, &rc->rc_retry);