git: dcfa3ee44da2 - main - nfsserver: Fix vrele() panic in nfsvno_open()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 13 Jan 2023 00:50:03 UTC
The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=dcfa3ee44da2b139f51a8aedb0f55735c6dfe3f3 commit dcfa3ee44da2b139f51a8aedb0f55735c6dfe3f3 Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2023-01-13 00:45:26 +0000 Commit: Rick Macklem <rmacklem@FreeBSD.org> CommitDate: 2023-01-13 00:48:53 +0000 nfsserver: Fix vrele() panic in nfsvno_open() Commit 65127e982b94 removed a check for ni_startdir != NULL. This allowed the vrele(ndp->ni_dvp) to be called with a NULL argument. This patch adds a new boolean argument to nfsvno_open() that can be checked instead of ni_startdir, since mjg@ requested that ni_startdir not be used. (Discussed in PR#268828.) PR: 268828 Reviewed by: mjg Differential Revision: https://reviews.freebsd.org/D38032 --- sys/fs/nfs/nfs_var.h | 2 +- sys/fs/nfsserver/nfs_nfsdport.c | 4 ++-- sys/fs/nfsserver/nfs_nfsdserv.c | 13 ++++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 6692bc19a725..f8fd2229095f 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -719,7 +719,7 @@ int nfsvno_statfs(vnode_t, struct statfs *); void nfsvno_getfs(struct nfsfsinfo *, int); void nfsvno_open(struct nfsrv_descript *, struct nameidata *, nfsquad_t, nfsv4stateid_t *, struct nfsstate *, int *, struct nfsvattr *, int32_t *, - int, NFSACL_T *, nfsattrbit_t *, struct ucred *, + int, NFSACL_T *, nfsattrbit_t *, struct ucred *, bool, struct nfsexstuff *, vnode_t *); int nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct nfsrv_descript *, NFSPROC_T *); diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 665e2c00ce08..d02653823857 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -1835,7 +1835,7 @@ void nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp, nfsquad_t clientid, nfsv4stateid_t *stateidp, struct nfsstate *stp, int *exclusive_flagp, struct nfsvattr *nvap, int32_t *cverf, int create, - NFSACL_T *aclp, nfsattrbit_t *attrbitp, struct ucred *cred, + NFSACL_T *aclp, nfsattrbit_t *attrbitp, struct ucred *cred, bool done_namei, struct nfsexstuff *exp, struct vnode **vpp) { struct vnode *vp = NULL; @@ -1918,7 +1918,7 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp, } } else { nfsvno_relpathbuf(ndp); - if (create == NFSV4OPEN_CREATE) { + if (done_namei && create == NFSV4OPEN_CREATE) { if (ndp->ni_dvp == ndp->ni_vp) vrele(ndp->ni_dvp); else diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index 709dc84d5d91..0433e9cda656 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -2830,13 +2830,14 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, u_long *hashp; NFSACL_T *aclp = NULL; struct thread *p = curthread; + bool done_namei; #ifdef NFS4_ACL_EXTATTR_NAME aclp = acl_alloc(M_WAITOK); aclp->acl_cnt = 0; #endif NFSZERO_ATTRBIT(&attrbits); - named.ni_startdir = NULL; + done_namei = false; named.ni_cnd.cn_nameiop = 0; NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); i = fxdr_unsigned(int, *(tl + 5)); @@ -3042,6 +3043,7 @@ 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); @@ -3049,7 +3051,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, if (create == NFSV4OPEN_CREATE) { switch (how) { case NFSCREATE_UNCHECKED: - if (named.ni_vp) { + if (done_namei && named.ni_vp != NULL) { /* * Clear the setable attribute bits, except * for Size, if it is being truncated. @@ -3061,12 +3063,13 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, } break; case NFSCREATE_GUARDED: - if (named.ni_vp && !nd->nd_repstat) + if (done_namei && named.ni_vp != NULL && + nd->nd_repstat == 0) nd->nd_repstat = EEXIST; break; case NFSCREATE_EXCLUSIVE: exclusive_flag = 1; - if (!named.ni_vp) + if (done_namei && named.ni_vp == NULL) nva.na_mode = 0; break; case NFSCREATE_EXCLUSIVE41: @@ -3076,7 +3079,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, } nfsvno_open(nd, &named, clientid, &stateid, stp, &exclusive_flag, &nva, cverf, create, aclp, &attrbits, - nd->nd_cred, exp, &vp); + nd->nd_cred, done_namei, exp, &vp); } else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim == NFSV4OPEN_CLAIMFH || claim == NFSV4OPEN_CLAIMDELEGATECURFH || claim == NFSV4OPEN_CLAIMDELEGATEPREVFH) {