Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Mar 2021 22:32:10 GMT
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 01ae8969a9ee - main - nfsd: do not implicitly bind the back channel for NFSv4.1/4.2 mounts
Message-ID:  <202103302232.12UMWA9R014678@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=01ae8969a9eed652fbd894faa5b31b1593079ed8

commit 01ae8969a9eed652fbd894faa5b31b1593079ed8
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2021-03-30 21:31:05 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2021-03-30 21:31:05 +0000

    nfsd: do not implicitly bind the back channel for NFSv4.1/4.2 mounts
    
    The NFSv4.1 (and 4.2 on 13) server incorrectly binds
    a new TCP connection to the back channel when first
    used by an RPC with a Sequence op in it (almost all of them).
    RFC5661 specifies that only the fore channel should be bound.
    
    This was done because early clients (including FreeBSD)
    did not do the required BindConnectionToSession RPC.
    
    Unfortunately, this breaks the Linux client when the
    "nconnects" mount option is used, since the server
    may do a callback on the incorrect TCP connection.
    
    This patch converts the server behaviour to that
    required by the RFC.  It also makes the server test/indicate
    failure of the back channel more aggressively.
    
    Until this patch is applied to the server, the
    "nconnects" mount option is not recommended for a Linux
    NFSv4.1/4.2 client mount to the FreeBSD server.
    
    Reported by:    bcodding@redhat.com
    Tested by:      bcodding@redhat.com
    PR:             254560
    MFC after:      1 week
---
 sys/fs/nfsserver/nfs_nfsdstate.c | 33 ++++-----------------------------
 1 file changed, 4 insertions(+), 29 deletions(-)

diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index 1f6e8b7ef526..5ac37ed07cae 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -6209,7 +6209,6 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
 	struct nfsdsession *sep;
 	struct nfssessionhash *shp;
 	int error;
-	SVCXPRT *savxprt;
 
 	shp = NFSSESSIONHASH(nd->nd_sessionid);
 	NFSLOCKSESSION(shp);
@@ -6235,36 +6234,11 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
 	nd->nd_maxreq = sep->sess_maxreq;
 	nd->nd_maxresp = sep->sess_maxresp;
 
-	/*
-	 * If this session handles the backchannel, save the nd_xprt for this
-	 * RPC, since this is the one being used.
-	 * RFC-5661 specifies that the fore channel will be implicitly
-	 * bound by a Sequence operation.  However, since some NFSv4.1 clients
-	 * erroneously assumed that the back channel would be implicitly
-	 * bound as well, do the implicit binding unless a
-	 * BindConnectiontoSession has already been done on the session.
-	 */
-	savxprt = NULL;
-	if (sep->sess_clp->lc_req.nr_client != NULL &&
-	    sep->sess_cbsess.nfsess_xprt != nd->nd_xprt &&
-	    (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0 &&
-	    (sep->sess_clp->lc_flags & LCL_DONEBINDCONN) == 0) {
-		NFSD_DEBUG(2,
-		    "nfsrv_checksequence: implicit back channel bind\n");
-		savxprt = sep->sess_cbsess.nfsess_xprt;
-		SVC_ACQUIRE(nd->nd_xprt);
-		nd->nd_xprt->xp_p2 =
-		    sep->sess_clp->lc_req.nr_client->cl_private;
-		nd->nd_xprt->xp_idletimeout = 0;	/* Disable timeout. */
-		sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
-	}
-
 	*sflagsp = 0;
-	if (sep->sess_clp->lc_req.nr_client == NULL)
+	if (sep->sess_clp->lc_req.nr_client == NULL ||
+	    (sep->sess_clp->lc_flags & LCL_CBDOWN) != 0)
 		*sflagsp |= NFSV4SEQ_CBPATHDOWN;
 	NFSUNLOCKSESSION(shp);
-	if (savxprt != NULL)
-		SVC_RELEASE(savxprt);
 	if (error == NFSERR_EXPIRED) {
 		*sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
 		error = 0;
@@ -6464,7 +6438,8 @@ nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
 				nd->nd_xprt->xp_idletimeout = 0;
 				sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
 				sep->sess_crflags |= NFSV4CRSESS_CONNBACKCHAN;
-				clp->lc_flags |= LCL_DONEBINDCONN;
+				clp->lc_flags |= LCL_DONEBINDCONN |
+				    LCL_NEEDSCBNULL;
 				if (*foreaftp == NFSCDFS4_BACK)
 					*foreaftp = NFSCDFS4_BACK;
 				else



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