svn commit: r363089 - in projects/nfs-over-tls/sys/rpc: . rpcsec_tls
Rick Macklem
rmacklem at FreeBSD.org
Sat Jul 11 03:39:45 UTC 2020
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. */
More information about the svn-src-projects
mailing list