From owner-svn-src-projects@freebsd.org Sat May 9 23:56:13 2020 Return-Path: Delivered-To: svn-src-projects@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id F3B132D2465 for ; Sat, 9 May 2020 23:56:13 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49KPH16F9Mz4T6P; Sat, 9 May 2020 23:56:13 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D0E242406C; Sat, 9 May 2020 23:56:13 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 049NuDsY046729; Sat, 9 May 2020 23:56:13 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 049NuDVe046728; Sat, 9 May 2020 23:56:13 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202005092356.049NuDVe046728@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Sat, 9 May 2020 23:56:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r360858 - projects/nfs-over-tls/sys/rpc X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfs-over-tls/sys/rpc X-SVN-Commit-Revision: 360858 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.32 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 09 May 2020 23:56:14 -0000 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. */