Date: Sat, 26 Jun 2021 22:53:27 GMT From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 54ccbc9bb6c5 - stable/13 - nfsd: Pre-parse the next NFSv4 operation number for put FH operations Message-ID: <202106262253.15QMrRPq054980@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=54ccbc9bb6c5a5077e8cda21902a6e9dc188c6cf commit 54ccbc9bb6c5a5077e8cda21902a6e9dc188c6cf Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2021-06-04 03:48:26 +0000 Commit: Rick Macklem <rmacklem@FreeBSD.org> 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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106262253.15QMrRPq054980>