summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlga Kornievskaia <kolga@netapp.com>2020-01-02 17:09:54 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2020-01-15 10:54:33 -0500
commit62a1573fcf844a559a79bec2eafc4309f2be5c5b (patch)
tree40264ba3186606cf36b0a3671f2c1fc954596e0f
parentc74dfe97c104bda5144bfa8193d8e5ea67d5da7f (diff)
NFSv4 fix acl retrieval over krb5i/krb5p mounts
For the krb5i and krb5p mount, it was problematic to truncate the received ACL to the provided buffer because an integrity check could not be preformed. Instead, provide enough pages to accommodate the largest buffer bounded by the largest RPC receive buffer size. Note: I don't think it's possible for the ACL to be truncated now. Thus NFS4_ACL_TRUNC flag and related code could be possibly removed but since I'm unsure, I'm leaving it. v2: needs +1 page. Signed-off-by: Olga Kornievskaia <kolga@netapp.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--fs/nfs/nfs4proc.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 294d27be3868..22175b85b586 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5601,10 +5601,9 @@ out:
*/
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
{
- struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, };
+ struct page **pages;
struct nfs_getaclargs args = {
.fh = NFS_FH(inode),
- .acl_pages = pages,
.acl_len = buflen,
};
struct nfs_getaclres res = {
@@ -5615,11 +5614,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
.rpc_argp = &args,
.rpc_resp = &res,
};
- unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
+ unsigned int npages;
int ret = -ENOMEM, i;
+ struct nfs_server *server = NFS_SERVER(inode);
- if (npages > ARRAY_SIZE(pages))
- return -ERANGE;
+ if (buflen == 0)
+ buflen = server->rsize;
+
+ npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
+ pages = kmalloc_array(npages, sizeof(struct page *), GFP_NOFS);
+ if (!pages)
+ return -ENOMEM;
+
+ args.acl_pages = pages;
for (i = 0; i < npages; i++) {
pages[i] = alloc_page(GFP_KERNEL);
@@ -5665,6 +5672,7 @@ out_free:
__free_page(pages[i]);
if (res.acl_scratch)
__free_page(res.acl_scratch);
+ kfree(pages);
return ret;
}