Commit 97e9a9ec authored by Rick Macklem's avatar Rick Macklem Committed by Chuck Lever
Browse files

NFSD: Add nfsd4_encode_fattr4_posix_access_acl



The POSIX ACL extension to NFSv4 defines FATTR4_POSIX_ACCESS_ACL
for retrieving the access ACL of a file or directory. This patch
adds the XDR encoder for that attribute.

The access ACL is retrieved via get_inode_acl(). If the filesystem
provides no explicit access ACL, one is synthesized from the file
mode via posix_acl_from_mode(). Each entry is encoded as a
posixace4: tag type, permission bits, and principal name (empty
for structural entries, resolved via idmapping for USER/GROUP
entries).

Unlike the default ACL encoder which applies only to directories,
this encoder handles all inode types and ensures an access ACL is
always available through mode-based synthesis when needed.

Signed-off-by: default avatarRick Macklem <rmacklem@uoguelph.ca>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 5e62c904
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -3016,6 +3016,7 @@ struct nfsd4_fattr_args {
#endif
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
	struct posix_acl	*dpacl;
	struct posix_acl	*pacl;
#endif
	u32			rdattr_err;
	bool			contextsupport;
@@ -3585,6 +3586,12 @@ static __be32 nfsd4_encode_fattr4_posix_default_acl(struct xdr_stream *xdr,
	return nfsd4_encode_posixacl(xdr, args->rqstp, args->dpacl);
}

static __be32 nfsd4_encode_fattr4_posix_access_acl(struct xdr_stream *xdr,
						   const struct nfsd4_fattr_args *args)
{
	return nfsd4_encode_posixacl(xdr, args->rqstp, args->pacl);
}

#endif /* CONFIG_NFSD_V4_POSIX_ACLS */

static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
@@ -3699,10 +3706,12 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
	[FATTR4_ACL_TRUEFORM]		= nfsd4_encode_fattr4_acl_trueform,
	[FATTR4_ACL_TRUEFORM_SCOPE]	= nfsd4_encode_fattr4_acl_trueform_scope,
	[FATTR4_POSIX_DEFAULT_ACL]	= nfsd4_encode_fattr4_posix_default_acl,
	[FATTR4_POSIX_ACCESS_ACL]	= nfsd4_encode_fattr4_posix_access_acl,
#else
	[FATTR4_ACL_TRUEFORM]		= nfsd4_encode_fattr4__noop,
	[FATTR4_ACL_TRUEFORM_SCOPE]	= nfsd4_encode_fattr4__noop,
	[FATTR4_POSIX_DEFAULT_ACL]	= nfsd4_encode_fattr4__noop,
	[FATTR4_POSIX_ACCESS_ACL]	= nfsd4_encode_fattr4__noop,
#endif
};

@@ -3746,6 +3755,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
#endif
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
	args.dpacl = NULL;
	args.pacl = NULL;
#endif

	/*
@@ -3877,6 +3887,29 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
			}
		}
	}
	if (attrmask[2] & FATTR4_WORD2_POSIX_ACCESS_ACL) {
		struct inode *inode = d_inode(dentry);
		struct posix_acl *pacl;

		pacl = get_inode_acl(inode, ACL_TYPE_ACCESS);
		if (!pacl)
			pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
		if (IS_ERR(pacl)) {
			switch (PTR_ERR(pacl)) {
			case -EOPNOTSUPP:
				attrmask[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL;
				break;
			case -EINVAL:
				status = nfserr_attrnotsupp;
				goto out;
			default:
				err = PTR_ERR(pacl);
				goto out_nfserr;
			}
		} else {
			args.pacl = pacl;
		}
	}
#endif /* CONFIG_NFSD_V4_POSIX_ACLS */

	/* attrmask */
@@ -3905,6 +3938,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
#ifdef CONFIG_NFSD_V4_POSIX_ACLS
	if (args.dpacl)
		posix_acl_release(args.dpacl);
	if (args.pacl)
		posix_acl_release(args.pacl);
#endif /* CONFIG_NFSD_V4_POSIX_ACLS */
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
	if (args.context.context)