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: