aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/nfs/nfs_var.h12
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c69
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c60
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;