git: ded5f2954e1a - main - nfsd: Fix handling of the error case for nfsvno_open
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 08 Feb 2023 21:09:46 UTC
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=ded5f2954e1a1bb7748646888938af767ee6257a
commit ded5f2954e1a1bb7748646888938af767ee6257a
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2023-02-08 21:06:07 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2023-02-08 21:08:51 +0000
nfsd: Fix handling of the error case for nfsvno_open
Using done_namei instead of ni_startdir did not
fix the crashes reported in the PR. Upon looking
more closely at the code, the only case where the
code near the end of nfsvno_open() needs to be
executed is when nfsvno_namei() has succeeded,
but a subsequent error was detected.
This patch uses done_namei to indicate this case.
Also, nfsvno_relpathbuf() should only be called for
this case and not whenever nfsvno_open() is called
with nd_repstat != 0. A bug was introduced here when
the HASBUF flag was deleted.
Reviewed by: mjg
PR: 268971
Tested by: ish@amail.plala.or.jp
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D38430
---
sys/fs/nfsserver/nfs_nfsdport.c | 22 +++++++++++++---------
sys/fs/nfsserver/nfs_nfsdserv.c | 10 +++++-----
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index d02653823857..7305ae6a84fe 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1916,16 +1916,20 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
stateidp, stp, vp, nd, p, nd->nd_repstat);
}
}
- } else {
+ } else if (done_namei) {
+ /*
+ * done_namei is set when nfsvno_namei() has completed
+ * successfully, but a subsequent error was set in
+ * nd_repstat. As such, cleanup of the nfsvno_namei()
+ * results is required.
+ */
nfsvno_relpathbuf(ndp);
- if (done_namei && create == NFSV4OPEN_CREATE) {
- if (ndp->ni_dvp == ndp->ni_vp)
- vrele(ndp->ni_dvp);
- else
- vput(ndp->ni_dvp);
- if (ndp->ni_vp)
- vput(ndp->ni_vp);
- }
+ if (ndp->ni_dvp == ndp->ni_vp)
+ vrele(ndp->ni_dvp);
+ else
+ vput(ndp->ni_dvp);
+ if (ndp->ni_vp)
+ vput(ndp->ni_vp);
}
*vpp = vp;
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 0433e9cda656..569ddc9141bb 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -3043,7 +3043,6 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp,
&dirp);
- done_namei = true;
} else {
vrele(dp);
nfsvno_relpathbuf(&named);
@@ -3051,7 +3050,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
if (create == NFSV4OPEN_CREATE) {
switch (how) {
case NFSCREATE_UNCHECKED:
- if (done_namei && named.ni_vp != NULL) {
+ if (nd->nd_repstat == 0 && named.ni_vp != NULL) {
/*
* Clear the setable attribute bits, except
* for Size, if it is being truncated.
@@ -3063,13 +3062,14 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
}
break;
case NFSCREATE_GUARDED:
- if (done_namei && named.ni_vp != NULL &&
- nd->nd_repstat == 0)
+ if (nd->nd_repstat == 0 && named.ni_vp != NULL) {
nd->nd_repstat = EEXIST;
+ done_namei = true;
+ }
break;
case NFSCREATE_EXCLUSIVE:
exclusive_flag = 1;
- if (done_namei && named.ni_vp == NULL)
+ if (nd->nd_repstat == 0 && named.ni_vp == NULL)
nva.na_mode = 0;
break;
case NFSCREATE_EXCLUSIVE41: