NFSD: Add an xdr_stream-based decoder for NFSv2/3 ACLs
[ Upstream commit 6bb844b4eb6e3b109a2fdaffb60e6da722dc4356 ] Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
ea6b0e02dc
commit
e077857ef0
@@ -295,3 +295,55 @@ int nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
|
|||||||
nfsacl_desc.desc.array_len;
|
nfsacl_desc.desc.array_len;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfsacl_decode);
|
EXPORT_SYMBOL_GPL(nfsacl_decode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfs_stream_decode_acl - Decode an NFSv3 ACL
|
||||||
|
*
|
||||||
|
* @xdr: an xdr_stream positioned at an encoded ACL
|
||||||
|
* @aclcnt: OUT: count of ACEs in decoded posix_acl
|
||||||
|
* @pacl: OUT: a dynamically-allocated buffer containing the decoded posix_acl
|
||||||
|
*
|
||||||
|
* Return values:
|
||||||
|
* %false: The encoded ACL is not valid
|
||||||
|
* %true: @pacl contains a decoded ACL, and @xdr is advanced
|
||||||
|
*
|
||||||
|
* On a successful return, caller must release *pacl using posix_acl_release().
|
||||||
|
*/
|
||||||
|
bool nfs_stream_decode_acl(struct xdr_stream *xdr, unsigned int *aclcnt,
|
||||||
|
struct posix_acl **pacl)
|
||||||
|
{
|
||||||
|
const size_t elem_size = XDR_UNIT * 3;
|
||||||
|
struct nfsacl_decode_desc nfsacl_desc = {
|
||||||
|
.desc = {
|
||||||
|
.elem_size = elem_size,
|
||||||
|
.xcode = pacl ? xdr_nfsace_decode : NULL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
unsigned int base;
|
||||||
|
u32 entries;
|
||||||
|
|
||||||
|
if (xdr_stream_decode_u32(xdr, &entries) < 0)
|
||||||
|
return false;
|
||||||
|
if (entries > NFS_ACL_MAX_ENTRIES)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
base = xdr_stream_pos(xdr);
|
||||||
|
if (!xdr_inline_decode(xdr, XDR_UNIT + elem_size * entries))
|
||||||
|
return false;
|
||||||
|
nfsacl_desc.desc.array_maxlen = entries;
|
||||||
|
if (xdr_decode_array2(xdr->buf, base, &nfsacl_desc.desc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pacl) {
|
||||||
|
if (entries != nfsacl_desc.desc.array_len ||
|
||||||
|
posix_acl_from_nfsacl(nfsacl_desc.acl) != 0) {
|
||||||
|
posix_acl_release(nfsacl_desc.acl);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*pacl = nfsacl_desc.acl;
|
||||||
|
}
|
||||||
|
if (aclcnt)
|
||||||
|
*aclcnt = entries;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nfs_stream_decode_acl);
|
||||||
|
@@ -38,5 +38,8 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
|
|||||||
extern int
|
extern int
|
||||||
nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
|
nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
|
||||||
struct posix_acl **pacl);
|
struct posix_acl **pacl);
|
||||||
|
extern bool
|
||||||
|
nfs_stream_decode_acl(struct xdr_stream *xdr, unsigned int *aclcnt,
|
||||||
|
struct posix_acl **pacl);
|
||||||
|
|
||||||
#endif /* __LINUX_NFSACL_H */
|
#endif /* __LINUX_NFSACL_H */
|
||||||
|
Reference in New Issue
Block a user