From owner-dev-commits-src-all@freebsd.org Sat Jun 26 22:53:27 2021 Return-Path: Delivered-To: dev-commits-src-all@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 9424465B38E; Sat, 26 Jun 2021 22:53:27 +0000 (UTC) (envelope-from git@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) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GC8Kz3nDWz3tj1; Sat, 26 Jun 2021 22:53:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6A0E82706C; Sat, 26 Jun 2021 22:53:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 15QMrRJS054981; Sat, 26 Jun 2021 22:53:27 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 15QMrRPq054980; Sat, 26 Jun 2021 22:53:27 GMT (envelope-from git) Date: Sat, 26 Jun 2021 22:53:27 GMT Message-Id: <202106262253.15QMrRPq054980@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Rick Macklem Subject: git: 54ccbc9bb6c5 - stable/13 - nfsd: Pre-parse the next NFSv4 operation number for put FH operations MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 54ccbc9bb6c5a5077e8cda21902a6e9dc188c6cf Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Jun 2021 22:53:27 -0000 The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=54ccbc9bb6c5a5077e8cda21902a6e9dc188c6cf commit 54ccbc9bb6c5a5077e8cda21902a6e9dc188c6cf Author: Rick Macklem AuthorDate: 2021-06-04 03:48:26 +0000 Commit: Rick Macklem CommitDate: 2021-06-26 22:50:16 +0000 nfsd: Pre-parse the next NFSv4 operation number for put FH operations RFC5661 Sec. 2.6 specifies when a NFSERR_WRONGSEC error reply can be done. For the four operations PutFH, PutrootFH, PutpublicFH and RestoreFH, NFSERR_WRONGSEC can or cannot be replied, depending upon what operation follows one of these operations in the compound. This patch modifies nfsrvd_compound() so that it parses the next operation number before executing any of the above four operations, storing it in "nextop". A future commit will implement use of "nextop" to decide if NFSERR_WRONGSEC can be replied for the above four operations. This commit should not change the semantics of performing the compound RPC. (cherry picked from commit d224f05fcfc13725c43ea0a02d511b3bf6a8ad14) --- sys/fs/nfsserver/nfs_nfsdsocket.c | 109 ++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index a8e1757835ac..f40569da0097 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -705,7 +705,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, int i, lktype, op, op0 = 0, statsinprog = 0; u_int32_t *tl; struct nfsclient *clp, *nclp; - int numops, error = 0, igotlock; + int error = 0, igotlock, nextop, numops, savefhcnt; u_int32_t retops = 0, *retopsp = NULL, *repp; vnode_t vp, nvp, savevp; struct nfsrvfh fh; @@ -822,6 +822,8 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, savevp = vp = NULL; save_fsid.val[0] = save_fsid.val[1] = 0; cur_fsid.val[0] = cur_fsid.val[1] = 0; + nextop = -1; + savefhcnt = 0; /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */ if (taglen < 0) { @@ -850,10 +852,20 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, * savevpnes and vpnes - are the export flags for the above. */ for (i = 0; i < numops; i++) { - NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED); - *repp = *tl; - op = fxdr_unsigned(int, *tl); + if (savefhcnt > 0) { + op = NFSV4OP_SAVEFH; + *repp = txdr_unsigned(op); + savefhcnt--; + } else if (nextop == -1) { + NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); + *repp = *tl; + op = fxdr_unsigned(int, *tl); + } else { + op = nextop; + *repp = txdr_unsigned(op); + nextop = -1; + } NFSD_DEBUG(4, "op=%d\n", op); if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS || (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) || @@ -950,6 +962,25 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, error = nfsrv_mtofh(nd, &fh); if (error) goto nfsmout; + if ((nd->nd_flag & ND_LASTOP) == 0) { + /* + * Pre-parse the next op#. If it is + * SaveFH, count it and skip to the + * next op#, if not the last op#. + * nextop is used to determine if + * NFSERR_WRONGSEC can be returned, + * per RFC5661 Sec. 2.6. + */ + do { + NFSM_DISSECT(tl, uint32_t *, + NFSX_UNSIGNED); + nextop = fxdr_unsigned(int, *tl); + if (nextop == NFSV4OP_SAVEFH && + i < numops - 1) + savefhcnt++; + } while (nextop == NFSV4OP_SAVEFH && + i < numops - 1); + } if (!nd->nd_repstat) nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, NULL, 0); @@ -964,11 +995,31 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, } break; case NFSV4OP_PUTPUBFH: - if (nfs_pubfhset) - nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, - &nes, NULL, 0); - else - nd->nd_repstat = NFSERR_NOFILEHANDLE; + if (nfs_pubfhset) { + if ((nd->nd_flag & ND_LASTOP) == 0) { + /* + * Pre-parse the next op#. If it is + * SaveFH, count it and skip to the + * next op#, if not the last op#. + * nextop is used to determine if + * NFSERR_WRONGSEC can be returned, + * per RFC5661 Sec. 2.6. + */ + do { + NFSM_DISSECT(tl, uint32_t *, + NFSX_UNSIGNED); + nextop = fxdr_unsigned(int, + *tl); + if (nextop == NFSV4OP_SAVEFH && + i < numops - 1) + savefhcnt++; + } while (nextop == NFSV4OP_SAVEFH && + i < numops - 1); + } + nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, + &nes, NULL, 0); + } else + nd->nd_repstat = NFSERR_NOFILEHANDLE; if (!nd->nd_repstat) { if (vp) vrele(vp); @@ -980,6 +1031,26 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, break; case NFSV4OP_PUTROOTFH: if (nfs_rootfhset) { + if ((nd->nd_flag & ND_LASTOP) == 0) { + /* + * Pre-parse the next op#. If it is + * SaveFH, count it and skip to the + * next op#, if not the last op#. + * nextop is used to determine if + * NFSERR_WRONGSEC can be returned, + * per RFC5661 Sec. 2.6. + */ + do { + NFSM_DISSECT(tl, uint32_t *, + NFSX_UNSIGNED); + nextop = fxdr_unsigned(int, + *tl); + if (nextop == NFSV4OP_SAVEFH && + i < numops - 1) + savefhcnt++; + } while (nextop == NFSV4OP_SAVEFH && + i < numops - 1); + } nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, &nes, NULL, 0); if (!nd->nd_repstat) { @@ -1016,6 +1087,26 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, break; case NFSV4OP_RESTOREFH: if (savevp) { + if ((nd->nd_flag & ND_LASTOP) == 0) { + /* + * Pre-parse the next op#. If it is + * SaveFH, count it and skip to the + * next op#, if not the last op#. + * nextop is used to determine if + * NFSERR_WRONGSEC can be returned, + * per RFC5661 Sec. 2.6. + */ + do { + NFSM_DISSECT(tl, uint32_t *, + NFSX_UNSIGNED); + nextop = fxdr_unsigned(int, + *tl); + if (nextop == NFSV4OP_SAVEFH && + i < numops - 1) + savefhcnt++; + } while (nextop == NFSV4OP_SAVEFH && + i < numops - 1); + } nd->nd_repstat = 0; /* If vp == savevp, a no-op */ if (vp != savevp) {