git: 6fd7e55c9413 - stable/15 - nfsd: Fix handling of hidden/system during Open/Create
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 24 Jan 2026 00:47:42 UTC
The branch stable/15 has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=6fd7e55c94134b01c6e0f14f53d3172f18ab786f
commit 6fd7e55c94134b01c6e0f14f53d3172f18ab786f
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2026-01-08 16:27:32 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2026-01-24 00:43:05 +0000
nfsd: Fix handling of hidden/system during Open/Create
When an NFSv4.n client specifies settings for the archive,
hidden and/or system attributes during a Open/Create, the
Open/Create fails for ZFS. This is caused by ZFS doing
a secpolicy_xvattr() call, which fails for non-root.
If this check is bypassed, ZFS panics.
This patch resolves the problem by disabling va_flags
for the VOP_CREATE() call in the NFSv4.n server and
then setting the flags with a subsequent VOP_SETATTR().
This problem only affects FreeBSD-15 and main, since the
archive, system and hidden attributes are not enabled
for FreeBSD-14.
I think a similar problem exists for the NFSv4.n
Open/Create/Exclusive_41, but that will be resolved
in a future commit.
Note that the Linux, Solaris and FreeBSD clients
do not set archive, hidden or system for Open/Create,
so the bug does not affect mounts from those clients.
PR: 292283
(cherry picked from commit a6d57f312f18bbeeda8a34e99d0a662b0db9a190)
---
sys/fs/nfsserver/nfs_nfsdport.c | 11 +++++++++++
sys/fs/nfsserver/nfs_nfsdsubs.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index c05e0d67f0d6..18e5813596c6 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1977,6 +1977,7 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
struct nfsexstuff nes;
struct thread *p = curthread;
uint32_t oldrepstat;
+ u_long savflags;
if (ndp->ni_vp == NULL) {
/*
@@ -1991,6 +1992,15 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
}
if (!nd->nd_repstat) {
if (ndp->ni_vp == NULL) {
+ /*
+ * Most file systems ignore va_flags for
+ * VOP_CREATE(), however setting va_flags
+ * for VOP_CREATE() causes problems for ZFS.
+ * So disable them and let nfsrv_fixattr()
+ * do them, as required.
+ */
+ savflags = nvap->na_flags;
+ nvap->na_flags = VNOVAL;
nd->nd_repstat = VOP_CREATE(ndp->ni_dvp,
&ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr);
/* For a pNFS server, create the data file on a DS. */
@@ -2003,6 +2013,7 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
nfsrv_pnfscreate(ndp->ni_vp, &nvap->na_vattr,
cred, p);
}
+ nvap->na_flags = savflags;
VOP_VPUT_PAIR(ndp->ni_dvp, nd->nd_repstat == 0 ?
&ndp->ni_vp : NULL, false);
nfsvno_relpathbuf(ndp);
diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c
index b09ec1b3a062..cc0e169af9b7 100644
--- a/sys/fs/nfsserver/nfs_nfsdsubs.c
+++ b/sys/fs/nfsserver/nfs_nfsdsubs.c
@@ -1697,6 +1697,44 @@ nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP);
}
}
+
+ /*
+ * For archive, ZFS sets it by default for new files,
+ * so if specified, it must be set or cleared.
+ * For hidden and system, no file system sets them
+ * by default upon creation, so they only need to be
+ * set and not cleared.
+ */
+ if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ARCHIVE)) {
+ if (nva.na_flags == VNOVAL)
+ nva.na_flags = 0;
+ if ((nvap->na_flags & UF_ARCHIVE) != 0)
+ nva.na_flags |= UF_ARCHIVE;
+ change++;
+ NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_ARCHIVE);
+ }
+ if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN)) {
+ if ((nvap->na_flags & UF_HIDDEN) != 0) {
+ if (nva.na_flags == VNOVAL)
+ nva.na_flags = 0;
+ nva.na_flags |= UF_HIDDEN;
+ change++;
+ NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_HIDDEN);
+ } else {
+ NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN);
+ }
+ }
+ if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SYSTEM)) {
+ if ((nvap->na_flags & UF_SYSTEM) != 0) {
+ if (nva.na_flags == VNOVAL)
+ nva.na_flags = 0;
+ nva.na_flags |= UF_SYSTEM;
+ change++;
+ NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_SYSTEM);
+ } else {
+ NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SYSTEM);
+ }
+ }
if (change) {
error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
if (error) {