Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Jul 2020 03:39:44 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r363089 - in projects/nfs-over-tls/sys/rpc: . rpcsec_tls
Message-ID:  <202007110339.06B3digg086633@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Jul 11 03:39:44 2020
New Revision: 363089
URL: https://svnweb.freebsd.org/changeset/base/363089

Log:
  Close a could of windows where, if the TLS upcall daemon terminated, the
  socket would not be closed properly.
  
  This patch closes these windows by setting the flag that indicates that
  a handshake is in progress just when the socket is associated with a
  file descriptor for the daemon.

Modified:
  projects/nfs-over-tls/sys/rpc/clnt_rc.c
  projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c

Modified: projects/nfs-over-tls/sys/rpc/clnt_rc.c
==============================================================================
--- projects/nfs-over-tls/sys/rpc/clnt_rc.c	Fri Jul 10 22:59:26 2020	(r363088)
+++ projects/nfs-over-tls/sys/rpc/clnt_rc.c	Sat Jul 11 03:39:44 2020	(r363089)
@@ -198,16 +198,6 @@ clnt_reconnect_connect(CLIENT *cl)
 		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
 		    rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr);
 		if (rc->rc_tls && newclient != NULL) {
-			/*
-			 * Set ssl refno so that clnt_vc_destroy() will not
-			 * close the socket and will leave that for the
-			 * daemon to do.  It is possible that the upcall
-			 * will time out, so that closing the socket via
-			 * the CLNT_CLOSE() below would happen too soon.
-			 */
-			ssl[0] = ssl[1] = 0;
-			ssl[2] = RPCTLS_REFNO_HANDSHAKE;
-			CLNT_CONTROL(newclient, CLSET_TLS, ssl);
 printf("at rpctls_connect\n");
 			stat = rpctls_connect(newclient, so, ssl, &reterr);
 printf("aft rpctls_connect=%d ssl=%jd\n", stat, (uintmax_t)ssl[2]);

Modified: projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c
==============================================================================
--- projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c	Fri Jul 10 22:59:26 2020	(r363088)
+++ projects/nfs-over-tls/sys/rpc/rpcsec_tls/rpctls_impl.c	Sat Jul 11 03:39:44 2020	(r363089)
@@ -75,14 +75,16 @@ static struct syscall_helper_data rpctls_syscalls[] = 
 static CLIENT		*rpctls_connect_handle;
 static struct mtx	rpctls_connect_lock;
 static struct socket	*rpctls_connect_so = NULL;
+static CLIENT		*rpctls_connect_cl = NULL;
 static CLIENT		*rpctls_server_handle;
 static struct mtx	rpctls_server_lock;
 static struct socket	*rpctls_server_so = NULL;
+static SVCXPRT		*rpctls_server_xprt = NULL;
 static struct opaque_auth rpctls_null_verf;
 
 static CLIENT		*rpctls_connect_client(void);
 static CLIENT		*rpctls_server_client(void);
-static enum clnt_stat	rpctls_server(struct socket *so,
+static enum clnt_stat	rpctls_server(SVCXPRT *xprt, struct socket *so,
 			    uint32_t *flags, uint64_t *sslp,
 			    uid_t *uid, int *ngrps, gid_t **gids);
 
@@ -113,9 +115,11 @@ sys_rpctls_syscall(struct thread *td, struct rpctls_sy
         struct netconfig *nconf;
 	struct file *fp;
 	struct socket *so;
+	SVCXPRT *xprt;
 	char path[MAXPATHLEN];
 	int fd = -1, error, try_count;
-	CLIENT *cl, *oldcl;
+	CLIENT *cl, *oldcl, *concl;
+	uint64_t ssl[3];
 	struct timeval timeo;
 #ifdef KERN_TLS
 	u_int maxlen;
@@ -272,11 +276,21 @@ printf("In connect\n");
 		mtx_lock(&rpctls_connect_lock);
 		so = rpctls_connect_so;
 		rpctls_connect_so = NULL;
+		concl = rpctls_connect_cl;
+		rpctls_connect_cl = NULL;
 		mtx_unlock(&rpctls_connect_lock);
 		if (so != NULL) {
 			error = falloc(td, &fp, &fd, 0);
 printf("falloc=%d fd=%d\n", error, fd);
 			if (error == 0) {
+				/*
+				 * Set ssl refno so that clnt_vc_destroy() will
+				 * not close the socket and will leave that for
+				 * the daemon to do.
+				 */
+				ssl[0] = ssl[1] = 0;
+				ssl[2] = RPCTLS_REFNO_HANDSHAKE;
+				CLNT_CONTROL(concl, CLSET_TLS, ssl);
 				finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so,
 				    &socketops);
 				fdrop(fp, td);	/* Drop fp reference. */
@@ -291,11 +305,21 @@ printf("In srvconnect\n");
 		mtx_lock(&rpctls_server_lock);
 		so = rpctls_server_so;
 		rpctls_server_so = NULL;
+		xprt = rpctls_server_xprt;
+		rpctls_server_xprt = NULL;
 		mtx_unlock(&rpctls_server_lock);
 		if (so != NULL) {
 			error = falloc(td, &fp, &fd, 0);
 printf("falloc=%d fd=%d\n", error, fd);
 			if (error == 0) {
+				/*
+				 * Once this file descriptor is associated
+				 * with the socket, it cannot be closed by
+				 * the server side krpc code (svc_vc.c).
+				 */
+				sx_xlock(&xprt->xp_lock);
+				xprt->xp_tls = RPCTLS_FLAGS_HANDSHFAIL;
+				sx_xunlock(&xprt->xp_lock);
 				finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so,
 				    &socketops);
 				fdrop(fp, td);	/* Drop fp reference. */
@@ -387,6 +411,7 @@ printf("aft NULLRPC=%d\n", stat);
 		    "rtlscn", 0);
 	rpctls_connect_busy = true;
 	rpctls_connect_so = so;
+	rpctls_connect_cl = newclient;
 	mtx_unlock(&rpctls_connect_lock);
 printf("rpctls_conect so=%p\n", so);
 
@@ -423,6 +448,7 @@ printf("did soshutdown rd\n");
 	/* Once the upcall is done, the daemon is done with the fp and so. */
 	mtx_lock(&rpctls_connect_lock);
 	rpctls_connect_so = NULL;
+	rpctls_connect_cl = NULL;
 	rpctls_connect_busy = false;
 	wakeup(&rpctls_connect_busy);
 	mtx_unlock(&rpctls_connect_lock);
@@ -551,7 +577,7 @@ printf("aft srv disconnect upcall=%d\n", stat);
 
 /* Do an upcall for a new server socket using TLS. */
 static enum clnt_stat
-rpctls_server(struct socket *so, uint32_t *flags, uint64_t *sslp,
+rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t *flags, uint64_t *sslp,
     uid_t *uid, int *ngrps, gid_t **gids)
 {
 	enum clnt_stat stat;
@@ -575,6 +601,7 @@ printf("server_client=%p\n", cl);
 		    "rtlssn", 0);
 	rpctls_server_busy = true;
 	rpctls_server_so = so;
+	rpctls_server_xprt = xprt;
 	mtx_unlock(&rpctls_server_lock);
 printf("rpctls_conect so=%p\n", so);
 
@@ -611,6 +638,7 @@ printf("aft server upcall stat=%d flags=0x%x\n", stat,
 	/* Once the upcall is done, the daemon is done with the fp and so. */
 	mtx_lock(&rpctls_server_lock);
 	rpctls_server_so = NULL;
+	rpctls_server_xprt = NULL;
 	rpctls_server_busy = false;
 	wakeup(&rpctls_server_busy);
 	mtx_unlock(&rpctls_server_lock);
@@ -686,7 +714,7 @@ printf("authtls: null reply=%d\n", call_stat);
 	}
 
 	/* Do an upcall to do the TLS handshake. */
-	stat = rpctls_server(rqst->rq_xprt->xp_socket, &flags,
+	stat = rpctls_server(xprt, xprt->xp_socket, &flags,
 	    ssl, &uid, &ngrps, &gidp);
 
 	/* Re-enable reception on the socket within the krpc. */
@@ -704,9 +732,6 @@ printf("authtls: null reply=%d\n", call_stat);
 			xprt->xp_gidp = gidp;
 printf("got uid=%d ngrps=%d gidp=%p\n", uid, ngrps, gidp);
 		}
-	} else {
-		/* Mark that TLS handshake failed. */
-		xprt->xp_tls = RPCTLS_FLAGS_HANDSHFAIL;
 	}
 	sx_xunlock(&xprt->xp_lock);
 	xprt_active(xprt);		/* Harmless if already active. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007110339.06B3digg086633>