diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/fs/nfs/nfs_var.h | 12 | ||||
| -rw-r--r-- | sys/fs/nfsclient/nfs_clrpcops.c | 69 | ||||
| -rw-r--r-- | 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 8cbfaa7a8996..0047be031ad5 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 714c37de271f..7ecd1619a0ad 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; @@ -4188,8 +4202,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); @@ -4669,6 +4683,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); @@ -4681,16 +4696,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) @@ -4750,7 +4767,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; |
