nfsd: Fix handling of attributes during Open/Create/Exclusive_41

When an NFSv4.n client specifies settings for attributes other
mode during a Open/Create/Exclusive_41, these other attributes
were not being set.

This patch resolves the problem by calling nfsrv_fixsattr()
after the VOP_CREATE() call in nfsvno_open() for this case.

There is no extant NFSv4.n client that currently does this,
as far as I know.

MFC after:	2 weeks
This commit is contained in:
Rick Macklem committed 2026-01-15 15:27:22 -08:00
1 parent 51786cdeb0
commit 4fc11c92d3
6 files changed
+57 -17

No files matched your search

+5
View File
@@ -872,6 +872,11 @@ typedef enum { UNKNOWN=0, DELETED=1, NLINK_ZERO=2, VALID=3 } nfsremove_status;
#define SUPPACL_NFSV4 1
#define SUPPACL_POSIX 2
/* Values NFSv4 uses for exclusive_flag. */
#define NFSV4_EXCLUSIVE_NONE 0
#define NFSV4_EXCLUSIVE 1
#define NFSV4_EXCLUSIVE_41 2
#endif /* _KERNEL */
#endif /* _NFS_NFS_H */
+1 -1
View File
@@ -410,7 +410,7 @@ int nfsv4_strtogid(struct nfsrv_descript *, u_char *, int, gid_t *);
int nfsrv_checkuidgid(struct nfsrv_descript *, struct nfsvattr *);
void nfsrv_fixattr(struct nfsrv_descript *, vnode_t,
struct nfsvattr *, NFSACL_T *, NFSACL_T *, NFSPROC_T *, nfsattrbit_t *,
struct nfsexstuff *);
bool);
int nfsrv_errmoved(int);
int nfsrv_putreferralattr(struct nfsrv_descript *, nfsattrbit_t *,
struct nfsreferral *, int, int *);
+2
View File
@@ -46,6 +46,8 @@
#define NFSVNO_ISSETATIME(n) ((n)->na_atime.tv_sec != VNOVAL)
#define NFSVNO_NOTSETMTIME(n) ((n)->na_mtime.tv_sec == VNOVAL)
#define NFSVNO_ISSETMTIME(n) ((n)->na_mtime.tv_sec != VNOVAL)
#define NFSVNO_NOTSETFLAGS(n) ((n)->na_flags == VNOVAL)
#define NFSVNO_ISSETFLAGS(n) ((n)->na_flags != VNOVAL)
/*
* This structure acts as a "catch-all" for information that
+38 -8
View File
@@ -1972,6 +1972,7 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
NFSACL_T *aclp, NFSACL_T *daclp, nfsattrbit_t *attrbitp, struct ucred *cred,
bool done_namei, struct nfsexstuff *exp, struct vnode **vpp)
{
struct vattr va;
struct vnode *vp = NULL;
u_quad_t tempsize;
struct nfsexstuff nes;
@@ -2018,23 +2019,52 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
&ndp->ni_vp : NULL, false);
nfsvno_relpathbuf(ndp);
if (!nd->nd_repstat) {
if (*exclusive_flagp) {
*exclusive_flagp = 0;
NFSVNO_ATTRINIT(nvap);
nvap->na_atime.tv_sec = cverf[0];
nvap->na_atime.tv_nsec = cverf[1];
if (*exclusive_flagp != NFSV4_EXCLUSIVE_NONE) {
VATTR_NULL(&va);
va.va_atime.tv_sec = cverf[0];
va.va_atime.tv_nsec = cverf[1];
nd->nd_repstat = VOP_SETATTR(ndp->ni_vp,
&nvap->na_vattr, cred);
&va, cred);
if (nd->nd_repstat != 0) {
vput(ndp->ni_vp);
ndp->ni_vp = NULL;
nd->nd_repstat = NFSERR_NOTSUPP;
} else
} else {
/*
* Few clients set these
* attributes in Open/Create
* Exclusive_41. If this
* changes, this should include
* setting atime, instead of
* the above.
*/
if (*exclusive_flagp ==
NFSV4_EXCLUSIVE_41 &&
(NFSISSET_ATTRBIT(attrbitp,
NFSATTRBIT_OWNER) ||
NFSISSET_ATTRBIT(attrbitp,
NFSATTRBIT_OWNERGROUP) ||
NFSISSET_ATTRBIT(attrbitp,
NFSATTRBIT_TIMEMODIFYSET)||
NFSISSET_ATTRBIT(attrbitp,
NFSATTRBIT_ARCHIVE) ||
NFSISSET_ATTRBIT(attrbitp,
NFSATTRBIT_HIDDEN) ||
NFSISSET_ATTRBIT(attrbitp,
NFSATTRBIT_SYSTEM) ||
aclp != NULL ||
daclp != NULL))
nfsrv_fixattr(nd,
ndp->ni_vp, nvap,
aclp, daclp, p,
attrbitp, true);
NFSSETBIT_ATTRBIT(attrbitp,
NFSATTRBIT_TIMEACCESS);
}
*exclusive_flagp = NFSV4_EXCLUSIVE_NONE;
} else {
nfsrv_fixattr(nd, ndp->ni_vp, nvap,
aclp, daclp, p, attrbitp, exp);
aclp, daclp, p, attrbitp, false);
}
}
vp = ndp->ni_vp;
+8 -5
View File
@@ -1608,7 +1608,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_repstat = nfsvno_mknod(&named, &nva, nd->nd_cred, p);
if (!nd->nd_repstat) {
vp = named.ni_vp;
nfsrv_fixattr(nd, vp, &nva, aclp, daclp, p, &attrbits, exp);
nfsrv_fixattr(nd, vp, &nva, aclp, daclp, p, &attrbits, false);
nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat)
nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
@@ -2120,7 +2120,7 @@ nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
!(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp);
if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) {
nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, NULL, p, attrbitp,
exp);
false);
if (nd->nd_flag & ND_NFSV3) {
nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p);
if (!nd->nd_repstat)
@@ -2255,7 +2255,7 @@ nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
nd->nd_cred, p, exp);
if (!nd->nd_repstat) {
vp = ndp->ni_vp;
nfsrv_fixattr(nd, vp, nvap, aclp, daclp, p, attrbitp, exp);
nfsrv_fixattr(nd, vp, nvap, aclp, daclp, p, attrbitp, false);
nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
nd->nd_repstat = nfsvno_getattr(vp, nvap, nd, p, 1,
@@ -2964,7 +2964,8 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
u_int32_t *tl;
int i, retext;
struct nfsstate *stp = NULL;
int error = 0, create, claim, exclusive_flag = 0, override;
int error = 0, create, claim, override;
int exclusive_flag = NFSV4_EXCLUSIVE_NONE;
u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
int how = NFSCREATE_UNCHECKED;
int32_t cverf[2], tverf[2] = { 0, 0 };
@@ -3229,6 +3230,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
case NFSCREATE_EXCLUSIVE:
if (nd->nd_repstat == 0 && named.ni_vp == NULL)
nva.na_mode = 0;
exclusive_flag = NFSV4_EXCLUSIVE;
/* FALLTHROUGH */
case NFSCREATE_EXCLUSIVE41:
if (nd->nd_repstat == 0 && named.ni_vp != NULL) {
@@ -3244,7 +3246,8 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat != 0)
done_namei = true;
}
exclusive_flag = 1;
if (how == NFSCREATE_EXCLUSIVE41)
exclusive_flag = NFSV4_EXCLUSIVE_41;
break;
}
}
+3 -3
View File
@@ -1645,7 +1645,7 @@ out:
void
nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
struct nfsvattr *nvap, NFSACL_T *aclp, NFSACL_T *daclp, NFSPROC_T *p,
nfsattrbit_t *attrbitp, struct nfsexstuff *exp)
nfsattrbit_t *attrbitp, bool atime_done)
{
int change = 0;
struct nfsvattr nva;
@@ -1675,7 +1675,7 @@ nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
}
}
if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) &&
NFSVNO_ISSETATIME(nvap)) {
!atime_done && NFSVNO_ISSETATIME(nvap)) {
nva.na_atime = nvap->na_atime;
change++;
NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET);
@@ -1736,7 +1736,7 @@ nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
}
}
if (change) {
error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, NULL);
if (error) {
NFSCLRALL_ATTRBIT(attrbitp, &nattrbits);
}