Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 May 2020 23:56:13 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r360858 - projects/nfs-over-tls/sys/rpc
Message-ID:  <202005092356.049NuDVe046728@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat May  9 23:56:13 2020
New Revision: 360858
URL: https://svnweb.freebsd.org/changeset/base/360858

Log:
  Add some very basic handling of TLS_GET_RECORD control mbufs for the
  client side krpc. For now, it just tosses away any non-application
  data records. This will probably need to change, but not until TLS1.3,
  I think?
  
  I also added code that shuts down the connection for a couple of
  cases that should rarely, if ever, happen:
  - If m_split(..,M_NOWAIT) returns NULL, the system is basically
    out of mbufs and I figured shutting down the TCP connection
    and then trying to create a new one is about as good as any
    other recovery. At least it doesn't end up hung waiting for more
    record data, which may never come.
  - If the RPC over TCP record mark is bogus, the connection is obviously
    no longer usable. This should never happen, but I have seen it
    recently during testing of the nfs-over-tls and I am not sure if
    it might still happen.

Modified:
  projects/nfs-over-tls/sys/rpc/clnt_vc.c

Modified: projects/nfs-over-tls/sys/rpc/clnt_vc.c
==============================================================================
--- projects/nfs-over-tls/sys/rpc/clnt_vc.c	Sat May  9 21:34:50 2020	(r360857)
+++ projects/nfs-over-tls/sys/rpc/clnt_vc.c	Sat May  9 23:56:13 2020	(r360858)
@@ -894,6 +894,8 @@ clnt_vc_destroy(CLIENT *cl)
 			soclose(so);
 		}
 	}
+	m_freem(ct->ct_record);
+	m_freem(ct->ct_raw);
 	mem_free(ct, sizeof(struct ct_data));
 	if (cl->cl_netid && cl->cl_netid[0])
 		mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
@@ -925,6 +927,8 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 	SVCXPRT *xprt;
 	struct cf_conn *cd;
 	u_int rawlen;
+	struct cmsghdr *cmsg;
+	struct tls_get_record tgr;
 
 	CTASSERT(sizeof(xid_plus_direction) == 2 * sizeof(uint32_t));
 
@@ -944,7 +948,9 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 	 * soreceive() is called.
 	 */
 	if (ct->ct_upcallrefs > 0)
+{ printf("soup another\n");
 		return (SU_OK);
+}
 	ct->ct_upcallrefs++;
 
 	/*
@@ -954,10 +960,10 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 	for (;;) {
 		uio.uio_resid = 1000000000;
 		uio.uio_td = curthread;
-		m = NULL;
+		m2 = m = NULL;
 		rcvflag = MSG_DONTWAIT | MSG_SOCALLBCK;
 		SOCKBUF_UNLOCK(&so->so_rcv);
-		error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
+		error = soreceive(so, NULL, &uio, &m, &m2, &rcvflag);
 		SOCKBUF_LOCK(&so->so_rcv);
 
 		if (error == EWOULDBLOCK) {
@@ -980,6 +986,7 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 			error = ECONNRESET;
 		}
 		if (error != 0) {
+		wakeup_all:
 			mtx_lock(&ct->ct_lock);
 			ct->ct_error.re_status = RPC_CANTRECV;
 			ct->ct_error.re_errno = error;
@@ -991,6 +998,30 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 			goto out;
 		}
 
+		/* Process any record header(s). */
+		if (m2 != NULL) {
+if (m2->m_next != NULL) printf("EEK! list of controls\n");
+			cmsg = mtod(m2, struct cmsghdr *);
+			if (cmsg->cmsg_type == TLS_GET_RECORD &&
+			    cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) {
+				memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr));
+				/*
+				 * For now, just toss non-application
+				 * data records.
+				 * In the future, there may need to be
+				 * an upcall done to the daemon, but
+				 * it cannot be done here.
+				 */
+				if (tgr.tls_type != TLS_RLTYPE_APP) {
+printf("Got weird type=%d\n", tgr.tls_type);
+					m_freem(m);
+					m_free(m2);
+					continue;
+				}
+			}
+			m_free(m2);
+		}
+
 		if (ct->ct_raw != NULL)
 			m_last(ct->ct_raw)->m_next = m;
 		else
@@ -1013,8 +1044,22 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
 			ct->ct_record = NULL;
 			ct->ct_record_resid = header & 0x7fffffff;
 			ct->ct_record_eor = ((header & 0x80000000) != 0);
-if (ct->ct_record_resid < 20 || ct->ct_record_resid > 70000 || !ct->ct_record_eor)
-printf("EEK!! recres=%zd eor=%d\n", ct->ct_record_resid, ct->ct_record_eor);
+			if (ct->ct_record_resid < 20 ||
+			    ct->ct_record_resid > 150000 ||
+			    !ct->ct_record_eor) {
+				printf("clnt_vc_soupcall: bogus record "
+				    "mark recres=%zd eor=%d\n",
+				    ct->ct_record_resid, ct->ct_record_eor);
+				/*
+				 * Connection is messed up. All we can
+				 * do now is shut it down and let
+				 * clnt_reconnect_XXX establish a new
+				 * connection.
+				 * This should never happen, but??
+				 */
+				error = ECONNRESET;
+				goto wakeup_all;
+			}
 			m_adj(ct->ct_raw, sizeof(uint32_t));
 			rawlen -= sizeof(uint32_t);
 		} else {
@@ -1036,8 +1081,22 @@ printf("EEK!! recres=%zd eor=%d\n", ct->ct_record_resi
 			} else {
 				m = m_split(ct->ct_raw, ct->ct_record_resid,
 				    M_NOWAIT);
-				if (m == NULL)
-					break;
+				if (m == NULL) {
+printf("soup m_split returned NULL\n");
+					/*
+					 * What to do now?
+					 * The system is out of mbufs.
+					 * I think it best to close this
+					 * connection and allow
+					 * clnt_reconnect_XXX() to try
+					 * and establish a new one.
+					 * If we just return and there are
+					 * no more data received, the
+					 * connection will be hung.
+					 */
+					error = ECONNRESET;
+					goto wakeup_all;
+				}
 				if (ct->ct_record != NULL)
 					m_last(ct->ct_record)->m_next =
 					    ct->ct_raw;
@@ -1076,9 +1135,11 @@ printf("EEK!! recres=%zd eor=%d\n", ct->ct_record_resi
 				    ntohl(xid_plus_direction[1]);
 				/* Check message direction. */
 				if (xid_plus_direction[1] == CALL) {
+printf("Got backchannel callback\n");
 					/* This is a backchannel request. */
 					mtx_lock(&ct->ct_lock);
 					xprt = ct->ct_backchannelxprt;
+printf("backxprt=%p\n", xprt);
 					if (xprt == NULL) {
 						mtx_unlock(&ct->ct_lock);
 						/* Just throw it away. */



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