The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=1749465947a807caa53ce09b90a30b820eaab62e
commit 1749465947a807caa53ce09b90a30b820eaab62e Author: Rick Macklem <rmack...@freebsd.org> AuthorDate: 2025-06-04 23:09:01 +0000 Commit: Rick Macklem <rmack...@freebsd.org> CommitDate: 2025-06-04 23:09:01 +0000 nfsd: Fix accumulating nfslockfile structures If a NFSv4 client does an exclusive open where the file already exists, the server returns EEXIST. However, without this patch, a partially filled in nfslockfile structure is allocated, but is not referenced by any open and, as such, never gets freed. This patch fixes the bug by checking for EEXIST before calling nfsvno_open(). Reported by: Christoper Iler <ci...@volexity.com> Tested by: Christoper Iler <ci...@volexity.com> MFC after: 2 weeks --- sys/fs/nfsserver/nfs_nfsdserv.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index b26fc59bcd6d..3f43e9115e28 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -2857,7 +2857,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, int how = NFSCREATE_UNCHECKED; int32_t cverf[2], tverf[2] = { 0, 0 }; vnode_t vp = NULL, dirp = NULL; - struct nfsvattr nva, dirfor, diraft; + struct nfsvattr nva, dirfor, diraft, nva2; struct nameidata named; nfsv4stateid_t stateid, delegstateid; nfsattrbit_t attrbits; @@ -3107,11 +3107,23 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, } break; case NFSCREATE_EXCLUSIVE: - exclusive_flag = 1; if (nd->nd_repstat == 0 && named.ni_vp == NULL) nva.na_mode = 0; - break; + /* FALLTHROUGH */ case NFSCREATE_EXCLUSIVE41: + if (nd->nd_repstat == 0 && named.ni_vp != NULL) { + nd->nd_repstat = nfsvno_getattr(named.ni_vp, + &nva2, nd, p, 1, NULL); + if (nd->nd_repstat == 0) { + tverf[0] = nva2.na_atime.tv_sec; + tverf[1] = nva2.na_atime.tv_nsec; + if (cverf[0] != tverf[0] || + cverf[1] != tverf[1])) + nd->nd_repstat = EEXIST; + } + if (nd->nd_repstat != 0) + done_namei = true; + } exclusive_flag = 1; break; } @@ -3201,16 +3213,8 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, NFSACCCHK_VPISLOCKED, NULL); } - if (!nd->nd_repstat) { + if (!nd->nd_repstat) nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); - if (!nd->nd_repstat) { - tverf[0] = nva.na_atime.tv_sec; - tverf[1] = nva.na_atime.tv_nsec; - } - } - if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] || - cverf[1] != tverf[1])) - nd->nd_repstat = EEXIST; /* * Do the open locking/delegation stuff. */