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
This commit is contained in:
Rick Macklem 2023-02-08 13:06:07 -08:00
parent fa3f665542
commit ded5f2954e
2 changed files with 18 additions and 14 deletions

View File

@ -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;

View File

@ -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: