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+
28522936static __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
34973590static 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
37803904out :
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