git: d224f05fcfc1 - main - nfsd: Pre-parse the next NFSv4 operation number for put FH operations
Rick Macklem
rmacklem at FreeBSD.org
Fri Jun 4 03:54:05 UTC 2021
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=d224f05fcfc13725c43ea0a02d511b3bf6a8ad14
commit d224f05fcfc13725c43ea0a02d511b3bf6a8ad14
Author: Rick Macklem <rmacklem at FreeBSD.org>
AuthorDate: 2021-06-04 03:48:26 +0000
Commit: Rick Macklem <rmacklem at FreeBSD.org>
CommitDate: 2021-06-04 03:48:26 +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.
MFC after: 2 weeks
---
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) {
More information about the dev-commits-src-main
mailing list