repo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 22 Dec 2025 02:06:36 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Rick Macklem Subject: git: 0e724de9ed6f - main - nfscl: Add some support for POSIX draft ACLs List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0e724de9ed6f2d2914cb79686a4ceee7f6dd31a1 Auto-Submitted: auto-generated Date: Mon, 22 Dec 2025 02:06:36 +0000 Message-Id: <6948a7ac.3651a.198c4314@gitrepo.freebsd.org> The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=0e724de9ed6f2d2914cb79686a4ceee7f6dd31a1 commit 0e724de9ed6f2d2914cb79686a4ceee7f6dd31a1 Author: Rick Macklem AuthorDate: 2025-12-22 02:05:04 +0000 Commit: Rick Macklem CommitDate: 2025-12-22 02:05:04 +0000 nfscl: Add some support for POSIX draft ACLs An internet draft (expected to become an RFC someday) https://datatracker.ietf.org/doc/draft-ietf-nfsv4-posix-acls describes an extension to NFSv4.2 to handle POSIX draft ACLs. This is the fourth of several patches that implement the above draft. There should be no semantics change for the series at this point. Fixes: a35bbd5d9f5f ("nfscommon: Add some support for POSIX draft ACLs") --- sys/fs/nfs/nfs_var.h | 12 ++++--- sys/fs/nfsclient/nfs_clrpcops.c | 69 +++++++++++++++++++++++++++++++---------- sys/fs/nfsclient/nfs_clvnops.c | 60 ++++++++++++++++++++++++++--------- 3 files changed, 105 insertions(+), 36 deletions(-) diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index c04c3951d42d..fe2462d94fd5 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -472,8 +472,8 @@ int nfsrpc_setclient(struct nfsmount *, struct nfsclclient *, int, int nfsrpc_getattr(vnode_t, struct ucred *, NFSPROC_T *, struct nfsvattr *); int nfsrpc_getattrnovp(struct nfsmount *, u_int8_t *, int, int, struct ucred *, NFSPROC_T *, struct nfsvattr *, u_int64_t *, uint32_t *); -int nfsrpc_setattr(vnode_t, struct vattr *, NFSACL_T *, struct ucred *, - NFSPROC_T *, struct nfsvattr *, int *); +int nfsrpc_setattr(vnode_t, struct vattr *, NFSACL_T *, acl_type_t, + struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); int nfsrpc_lookup(vnode_t, char *, int, struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, struct nfsfh **, int *, int *, uint32_t); @@ -526,7 +526,7 @@ int nfsrpc_statfs(vnode_t, struct nfsstatfs *, struct nfsfsinfo *, uint32_t *, int nfsrpc_fsinfo(vnode_t, struct nfsfsinfo *, struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); int nfsrpc_pathconf(vnode_t, struct nfsv3_pathconf *, bool *, uint32_t *, - struct ucred *, NFSPROC_T *, struct nfsvattr *, int *); + struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, uint32_t *); int nfsrpc_renew(struct nfsclclient *, struct nfsclds *, struct ucred *, NFSPROC_T *); int nfsrpc_rellockown(struct nfsmount *, struct nfscllockowner *, uint8_t *, @@ -535,8 +535,10 @@ int nfsrpc_getdirpath(struct nfsmount *, u_char *, struct ucred *, NFSPROC_T *); int nfsrpc_delegreturn(struct nfscldeleg *, struct ucred *, struct nfsmount *, NFSPROC_T *, int); -int nfsrpc_getacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *); -int nfsrpc_setacl(vnode_t, struct ucred *, NFSPROC_T *, NFSACL_T *); +int nfsrpc_getacl(struct vnode *, acl_type_t, struct ucred *, NFSPROC_T *, + NFSACL_T *); +int nfsrpc_setacl(struct vnode *, acl_type_t, struct ucred *, NFSPROC_T *, + NFSACL_T *); int nfsrpc_exchangeid(struct nfsmount *, struct nfsclclient *, struct nfssockreq *, int, uint32_t, struct nfsclds **, struct ucred *, NFSPROC_T *); diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index f5deef183efb..47f880d2a96a 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -147,7 +147,7 @@ static int nfsrpc_locku(struct nfsrv_descript *, struct nfsmount *, struct nfscllockowner *, u_int64_t, u_int64_t, u_int32_t, struct ucred *, NFSPROC_T *, int); static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *, - struct acl *, nfsv4stateid_t *); + struct acl *, acl_type_t, nfsv4stateid_t *); static int nfsrpc_layouterror(struct nfsmount *, uint8_t *, int, uint64_t, uint64_t, nfsv4stateid_t *, struct ucred *, NFSPROC_T *, uint32_t, uint32_t, char *); @@ -1371,7 +1371,7 @@ nfsrpc_getattrnovp(struct nfsmount *nmp, u_int8_t *fhp, int fhlen, int syscred, * Do an nfs setattr operation. */ int -nfsrpc_setattr(vnode_t vp, struct vattr *vap, NFSACL_T *aclp, +nfsrpc_setattr(vnode_t vp, struct vattr *vap, NFSACL_T *aclp, acl_type_t aclt, struct ucred *cred, NFSPROC_T *p, struct nfsvattr *rnap, int *attrflagp) { int error, expireret = 0, openerr, retrycnt; @@ -1418,7 +1418,8 @@ nfsrpc_setattr(vnode_t vp, struct vattr *vap, NFSACL_T *aclp, error = nfsrpc_setattrrpc(vp, vap, &stateid, cred, p, rnap, attrflagp); else - error = nfsrpc_setaclrpc(vp, cred, p, aclp, &stateid); + error = nfsrpc_setaclrpc(vp, cred, p, aclp, aclt, + &stateid); if (error == NFSERR_OPENMODE && mode == NFSV4OPEN_ACCESSREAD) { NFSLOCKMNT(nmp); nmp->nm_state |= NFSSTA_OPENMODE; @@ -5072,7 +5073,7 @@ nfsmout: int nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc, bool *has_namedattrp, uint32_t *clone_blksizep, struct ucred *cred, NFSPROC_T *p, - struct nfsvattr *nap, int *attrflagp) + struct nfsvattr *nap, int *attrflagp, uint32_t *trueformp) { struct nfsrv_descript nfsd, *nd = &nfsd; struct nfsmount *nmp; @@ -5102,6 +5103,8 @@ nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc, bool *has_namedattrp, */ NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp, cred); NFSPATHCONF_GETATTRBIT(&attrbits); + if (nmp->nm_minorvers >= NFSV42_MINORVERSION) + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACLTRUEFORM); (void) nfsrv_putattrbit(nd, &attrbits); nd->nd_flag |= ND_USEGSSNAME; error = nfscl_request(nd, vp, p, cred); @@ -5391,26 +5394,43 @@ nfsrpc_delegreturn(struct nfscldeleg *dp, struct ucred *cred, * nfs getacl call. */ int -nfsrpc_getacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp) +nfsrpc_getacl(struct vnode *vp, acl_type_t acltype, struct ucred *cred, + NFSPROC_T *p, struct acl *aclp) { struct nfsrv_descript nfsd, *nd = &nfsd; int error; nfsattrbit_t attrbits; struct nfsmount *nmp = VFSTONFS(vp->v_mount); + struct nfsnode *np; if (nfsrv_useacl == 0 || !NFSHASNFSV4(nmp)) return (EOPNOTSUPP); + np = VTONFS(vp); + if (!NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, NFSATTRBIT_ACL) && + acltype == ACL_TYPE_NFS4) + return (EOPNOTSUPP); + if ((!NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, + NFSATTRBIT_POSIXACCESSACL) || + !NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, + NFSATTRBIT_POSIXDEFAULTACL)) && + (acltype == ACL_TYPE_ACCESS || acltype == ACL_TYPE_DEFAULT)) + return (EOPNOTSUPP); NFSCL_REQSTART(nd, NFSPROC_GETACL, vp, cred); NFSZERO_ATTRBIT(&attrbits); - NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); + if (acltype == ACL_TYPE_NFS4) + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); + else if (acltype == ACL_TYPE_ACCESS) + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_POSIXACCESSACL); + else + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_POSIXDEFAULTACL); (void) nfsrv_putattrbit(nd, &attrbits); error = nfscl_request(nd, vp, p, cred); if (error) return (error); if (!nd->nd_repstat) error = nfsv4_loadattr(nd, vp, NULL, NULL, NULL, 0, NULL, - NULL, NULL, NULL, aclp, 0, NULL, NULL, NULL, NULL, NULL, p, - cred); + NULL, NULL, NULL, aclp, 0, NULL, NULL, NULL, NULL, NULL, + p, cred); else error = nd->nd_repstat; m_freem(nd->nd_mrep); @@ -5421,14 +5441,26 @@ nfsrpc_getacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp) * nfs setacl call. */ int -nfsrpc_setacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp) +nfsrpc_setacl(struct vnode *vp, acl_type_t acltype, struct ucred *cred, + NFSPROC_T *p, struct acl *aclp) { int error; struct nfsmount *nmp = VFSTONFS(vp->v_mount); + struct nfsnode *np; if (nfsrv_useacl == 0 || !NFSHASNFSV4(nmp)) return (EOPNOTSUPP); - error = nfsrpc_setattr(vp, NULL, aclp, cred, p, NULL, NULL); + np = VTONFS(vp); + if (!NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, NFSATTRBIT_ACL) && + acltype == ACL_TYPE_NFS4) + return (EOPNOTSUPP); + if ((!NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, + NFSATTRBIT_POSIXACCESSACL) || + !NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, + NFSATTRBIT_POSIXDEFAULTACL)) && + (acltype == ACL_TYPE_ACCESS || acltype == ACL_TYPE_DEFAULT)) + return (EOPNOTSUPP); + error = nfsrpc_setattr(vp, NULL, aclp, acltype, cred, p, NULL, NULL); return (error); } @@ -5436,8 +5468,8 @@ nfsrpc_setacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp) * nfs setacl call. */ static int -nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p, - struct acl *aclp, nfsv4stateid_t *stateidp) +nfsrpc_setaclrpc(struct vnode *vp, struct ucred *cred, NFSPROC_T *p, + struct acl *aclp, acl_type_t aclt, nfsv4stateid_t *stateidp) { struct nfsrv_descript nfsd, *nd = &nfsd; int error; @@ -5449,10 +5481,15 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p, NFSCL_REQSTART(nd, NFSPROC_SETACL, vp, cred); nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID); NFSZERO_ATTRBIT(&attrbits); - NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); - (void) nfsv4_fillattr(nd, vp->v_mount, vp, aclp, NULL, NULL, 0, - &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, false, false, - false, 0, NULL, false); + if (aclt == ACL_TYPE_NFS4) + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); + else if (aclt == ACL_TYPE_ACCESS) + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_POSIXACCESSACL); + else + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_POSIXDEFAULTACL); + (void)nfsv4_fillattr(nd, vp->v_mount, vp, aclp, NULL, NULL, 0, + &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, false, + false, false, 0, NULL, false); error = nfscl_request(nd, vp, p, cred); if (error) return (error); diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 193d8b6cd5eb..7484a5a7e082 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1215,7 +1215,7 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred, NFSUNLOCKNODE(np); KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp); } - error = nfsrpc_setattr(vp, vap, NULL, cred, td, &nfsva, &attrflag); + error = nfsrpc_setattr(vp, vap, NULL, 0, cred, td, &nfsva, &attrflag); if (attrflag) { ret = nfscl_loadattrcache(&vp, &nfsva, NULL, 0, 1); if (ret && !error) @@ -1967,14 +1967,14 @@ again: } } else if (NFS_ISV34(dvp) && (fmode & O_EXCL)) { if (nfscl_checksattr(vap, &nfsva)) { - error = nfsrpc_setattr(newvp, vap, NULL, cnp->cn_cred, - curthread, &nfsva, &attrflag); + error = nfsrpc_setattr(newvp, vap, NULL, 0, + cnp->cn_cred, curthread, &nfsva, &attrflag); if (error && (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL)) { /* try again without setting uid/gid */ vap->va_uid = (uid_t)VNOVAL; vap->va_gid = (uid_t)VNOVAL; - error = nfsrpc_setattr(newvp, vap, NULL, + error = nfsrpc_setattr(newvp, vap, NULL, 0, cnp->cn_cred, curthread, &nfsva, &attrflag); } if (attrflag) @@ -3772,9 +3772,15 @@ nfs_getacl(struct vop_getacl_args *ap) { int error; - if (ap->a_type != ACL_TYPE_NFS4) + if (ap->a_type != ACL_TYPE_NFS4 && ap->a_type != ACL_TYPE_ACCESS && + ap->a_type != ACL_TYPE_DEFAULT) + return (EOPNOTSUPP); + if (ap->a_type == ACL_TYPE_DEFAULT && ap->a_vp->v_type != VDIR) + return (EINVAL); + error = nfsrpc_getacl(ap->a_vp, ap->a_type, ap->a_cred, ap->a_td, + ap->a_aclp); + if (error == 0 && ap->a_aclp->acl_cnt == 0) return (EOPNOTSUPP); - error = nfsrpc_getacl(ap->a_vp, ap->a_cred, ap->a_td, ap->a_aclp); if (error > NFSERR_STALE) { (void) nfscl_maperr(ap->a_td, error, (uid_t)0, (gid_t)0); error = EPERM; @@ -3787,9 +3793,17 @@ nfs_setacl(struct vop_setacl_args *ap) { int error; - if (ap->a_type != ACL_TYPE_NFS4) + if (ap->a_type != ACL_TYPE_NFS4 && ap->a_type != ACL_TYPE_ACCESS && + ap->a_type != ACL_TYPE_DEFAULT) return (EOPNOTSUPP); - error = nfsrpc_setacl(ap->a_vp, ap->a_cred, ap->a_td, ap->a_aclp); + if (ap->a_aclp == NULL) { + if (ap->a_type != ACL_TYPE_DEFAULT) + return (EINVAL); + if (ap->a_vp->v_type != VDIR) + return (ENOTDIR); + } + error = nfsrpc_setacl(ap->a_vp, ap->a_type, ap->a_cred, ap->a_td, + ap->a_aclp); if (error > NFSERR_STALE) { (void) nfscl_maperr(ap->a_td, error, (uid_t)0, (gid_t)0); error = EPERM; @@ -4192,8 +4206,8 @@ relock: va.va_vaflags = VA_UTIMES_NULL; inattrflag = 0; error = nfsrpc_setattr(invp, &va, NULL, - ap->a_incred, curthread, &innfsva, - &inattrflag); + 0, ap->a_incred, curthread, + &innfsva, &inattrflag); if (inattrflag != 0) ret = nfscl_loadattrcache(&invp, &innfsva, NULL, 0, 1); @@ -4673,6 +4687,7 @@ nfs_pathconf(struct vop_pathconf_args *ap) bool eof, has_namedattr, named_enabled; int attrflag, error; struct nfsnode *np; + uint32_t trueform; nmp = VFSTONFS(vp->v_mount); np = VTONFS(vp); @@ -4685,16 +4700,18 @@ nfs_pathconf(struct vop_pathconf_args *ap) ap->a_name == _PC_CASE_INSENSITIVE)) || (NFS_ISV4(vp) && (ap->a_name == _PC_ACL_NFS4 || ap->a_name == _PC_HAS_NAMEDATTR || - ap->a_name == _PC_CLONE_BLKSIZE))) { + ap->a_name == _PC_CLONE_BLKSIZE || + ap->a_name == _PC_ACL_EXTENDED))) { /* * Since only the above 5 a_names are returned by the NFSv3 * Pathconf RPC, there is no point in doing it for others. * For NFSv4, the Pathconf RPC (actually a Getattr Op.) can - * be used for _PC_ACL_NFS4, _PC_HAS_NAMEDATTR and - * _PC_CLONE_BLKSIZE as well. + * be used for _PC_ACL_NFS4, _PC_HAS_NAMEDATTR, + * and _PC_ACL_EXTENDED as well. */ + trueform = UINT32_MAX; error = nfsrpc_pathconf(vp, &pc, &has_namedattr, &clone_blksize, - td->td_ucred, td, &nfsva, &attrflag); + td->td_ucred, td, &nfsva, &attrflag, &trueform); if (attrflag != 0) (void) nfscl_loadattrcache(&vp, &nfsva, NULL, 0, 1); if (error != 0) @@ -4754,7 +4771,20 @@ nfs_pathconf(struct vop_pathconf_args *ap) break; case _PC_ACL_NFS4: if (NFS_ISV4(vp) && nfsrv_useacl != 0 && attrflag != 0 && - NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) + NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL) && + (trueform == NFSV4_ACL_MODEL_NFS4 || + trueform == UINT32_MAX)) + *ap->a_retval = 1; + else + *ap->a_retval = 0; + break; + case _PC_ACL_EXTENDED: + if (NFS_ISV4(vp) && nfsrv_useacl != 0 && attrflag != 0 && + NFSISSET_ATTRBIT(&nfsva.na_suppattr, + NFSATTRBIT_POSIXACCESSACL) && + NFSISSET_ATTRBIT(&nfsva.na_suppattr, + NFSATTRBIT_POSIXDEFAULTACL) && + trueform == NFSV4_ACL_MODEL_POSIX_DRAFT) *ap->a_retval = 1; else *ap->a_retval = 0;