Skip to content

Commit 5e62c90

Browse files
rmacklemchucklever
authored andcommitted
NFSD: Add nfsd4_encode_fattr4_posix_default_acl
The POSIX ACL extension to NFSv4 defines FATTR4_POSIX_DEFAULT_ACL for retrieving a directory's default ACL. This patch adds the XDR encoder for that attribute. For directories, the default ACL is retrieved via get_inode_acl() and each entry is encoded as a posixace4: tag type, permission bits, and principal name (empty for structural entries like USER_OBJ/GROUP_OBJ/MASK/OTHER, resolved via idmapping for USER/GROUP entries). Signed-off-by: Rick Macklem <rmacklem@uoguelph.ca> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 8093c31 commit 5e62c90

1 file changed

Lines changed: 128 additions & 0 deletions

File tree

fs/nfsd/nfs4xdr.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <linux/sunrpc/addr.h>
4444
#include <linux/xattr.h>
4545
#include <linux/vmalloc.h>
46+
#include <linux/nfsacl.h>
4647

4748
#include <uapi/linux/xattr.h>
4849

@@ -2849,6 +2850,89 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
28492850
{ return 0; }
28502851
#endif
28512852

2853+
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
2854+
2855+
static int nfsd4_posix_tagtotype(short tag)
2856+
{
2857+
switch (tag) {
2858+
case ACL_USER_OBJ: return POSIXACE4_TAG_USER_OBJ;
2859+
case ACL_GROUP_OBJ: return POSIXACE4_TAG_GROUP_OBJ;
2860+
case ACL_USER: return POSIXACE4_TAG_USER;
2861+
case ACL_GROUP: return POSIXACE4_TAG_GROUP;
2862+
case ACL_MASK: return POSIXACE4_TAG_MASK;
2863+
case ACL_OTHER: return POSIXACE4_TAG_OTHER;
2864+
default: return -EINVAL;
2865+
}
2866+
}
2867+
2868+
static __be32
2869+
nfsd4_encode_posixace4(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2870+
struct posix_acl_entry *acep)
2871+
{
2872+
__be32 status;
2873+
int type;
2874+
2875+
type = nfsd4_posix_tagtotype(acep->e_tag);
2876+
if (type < 0)
2877+
return nfserr_resource;
2878+
if (!xdrgen_encode_posixacetag4(xdr, type))
2879+
return nfserr_resource;
2880+
if (!xdrgen_encode_posixaceperm4(xdr, acep->e_perm))
2881+
return nfserr_resource;
2882+
2883+
/* who */
2884+
switch (acep->e_tag) {
2885+
case ACL_USER_OBJ:
2886+
case ACL_GROUP_OBJ:
2887+
case ACL_MASK:
2888+
case ACL_OTHER:
2889+
if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
2890+
return nfserr_resource;
2891+
break;
2892+
case ACL_USER:
2893+
status = nfsd4_encode_user(xdr, rqstp, acep->e_uid);
2894+
if (status != nfs_ok)
2895+
return status;
2896+
break;
2897+
case ACL_GROUP:
2898+
status = nfsd4_encode_group(xdr, rqstp, acep->e_gid);
2899+
if (status != nfs_ok)
2900+
return status;
2901+
break;
2902+
default:
2903+
return nfserr_resource;
2904+
}
2905+
return nfs_ok;
2906+
}
2907+
2908+
static __be32
2909+
nfsd4_encode_posixacl(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2910+
struct posix_acl *acl)
2911+
{
2912+
__be32 status;
2913+
int i;
2914+
2915+
if (!acl) {
2916+
if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
2917+
return nfserr_resource;
2918+
return nfs_ok;
2919+
}
2920+
2921+
if (acl->a_count > NFS_ACL_MAX_ENTRIES)
2922+
return nfserr_resource;
2923+
if (xdr_stream_encode_u32(xdr, acl->a_count) != XDR_UNIT)
2924+
return nfserr_resource;
2925+
for (i = 0; i < acl->a_count; i++) {
2926+
status = nfsd4_encode_posixace4(xdr, rqstp, &acl->a_entries[i]);
2927+
if (status != nfs_ok)
2928+
return status;
2929+
}
2930+
2931+
return nfs_ok;
2932+
}
2933+
2934+
#endif /* CONFIG_NFSD_V4_POSIX_ACL */
2935+
28522936
static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *bmval2, u32 *rdattr_err)
28532937
{
28542938
/* As per referral draft: */
@@ -2929,6 +3013,9 @@ struct nfsd4_fattr_args {
29293013
u64 change_attr;
29303014
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
29313015
struct lsm_context context;
3016+
#endif
3017+
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
3018+
struct posix_acl *dpacl;
29323019
#endif
29333020
u32 rdattr_err;
29343021
bool contextsupport;
@@ -3492,6 +3579,12 @@ static __be32 nfsd4_encode_fattr4_acl_trueform_scope(struct xdr_stream *xdr,
34923579
return nfs_ok;
34933580
}
34943581

3582+
static __be32 nfsd4_encode_fattr4_posix_default_acl(struct xdr_stream *xdr,
3583+
const struct nfsd4_fattr_args *args)
3584+
{
3585+
return nfsd4_encode_posixacl(xdr, args->rqstp, args->dpacl);
3586+
}
3587+
34953588
#endif /* CONFIG_NFSD_V4_POSIX_ACLS */
34963589

34973590
static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
@@ -3605,9 +3698,11 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
36053698
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
36063699
[FATTR4_ACL_TRUEFORM] = nfsd4_encode_fattr4_acl_trueform,
36073700
[FATTR4_ACL_TRUEFORM_SCOPE] = nfsd4_encode_fattr4_acl_trueform_scope,
3701+
[FATTR4_POSIX_DEFAULT_ACL] = nfsd4_encode_fattr4_posix_default_acl,
36083702
#else
36093703
[FATTR4_ACL_TRUEFORM] = nfsd4_encode_fattr4__noop,
36103704
[FATTR4_ACL_TRUEFORM_SCOPE] = nfsd4_encode_fattr4__noop,
3705+
[FATTR4_POSIX_DEFAULT_ACL] = nfsd4_encode_fattr4__noop,
36113706
#endif
36123707
};
36133708

@@ -3649,6 +3744,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
36493744
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
36503745
args.context.context = NULL;
36513746
#endif
3747+
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
3748+
args.dpacl = NULL;
3749+
#endif
36523750

36533751
/*
36543752
* Make a local copy of the attribute bitmap that can be modified.
@@ -3755,6 +3853,32 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
37553853
}
37563854
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
37573855

3856+
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
3857+
if (attrmask[2] & FATTR4_WORD2_POSIX_DEFAULT_ACL) {
3858+
struct inode *inode = d_inode(dentry);
3859+
struct posix_acl *dpacl;
3860+
3861+
if (S_ISDIR(inode->i_mode)) {
3862+
dpacl = get_inode_acl(inode, ACL_TYPE_DEFAULT);
3863+
if (IS_ERR(dpacl)) {
3864+
switch (PTR_ERR(dpacl)) {
3865+
case -EOPNOTSUPP:
3866+
attrmask[2] &= ~FATTR4_WORD2_POSIX_DEFAULT_ACL;
3867+
break;
3868+
case -EINVAL:
3869+
status = nfserr_attrnotsupp;
3870+
goto out;
3871+
default:
3872+
err = PTR_ERR(dpacl);
3873+
goto out_nfserr;
3874+
}
3875+
} else {
3876+
args.dpacl = dpacl;
3877+
}
3878+
}
3879+
}
3880+
#endif /* CONFIG_NFSD_V4_POSIX_ACLS */
3881+
37583882
/* attrmask */
37593883
status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1],
37603884
attrmask[2]);
@@ -3778,6 +3902,10 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
37783902
status = nfs_ok;
37793903

37803904
out:
3905+
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
3906+
if (args.dpacl)
3907+
posix_acl_release(args.dpacl);
3908+
#endif /* CONFIG_NFSD_V4_POSIX_ACLS */
37813909
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
37823910
if (args.context.context)
37833911
security_release_secctx(&args.context);

0 commit comments

Comments
 (0)