[PATCH 27/33] xfs: lift buffer allocation into xfs_ioc_attr_list

Christoph Hellwig
2019-12-12T10:55:41Z

Lift the buffer allocation from the two callers into xfs_ioc_attr_list.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_ioctl.c | 39 ++++++++++++++++-----------------------
fs/xfs/xfs_ioctl.h | 2 +-
fs/xfs/xfs_ioctl32.c | 22 +++++-----------------
3 files changed, 22 insertions(+), 41 deletions(-)

diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 2cc53da070e7..f4b1aee0f362 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -353,13 +353,14 @@ xfs_ioc_attr_put_listent(
int
xfs_ioc_attr_list(
struct xfs_inode *dp,
- char *buffer,
+ void __user *ubuf,
int bufsize,
int flags,
struct attrlist_cursor_kern *cursor)
{
struct xfs_attr_list_context context;
struct xfs_attrlist *alist;
+ void *buffer;
int error;

if (bufsize < sizeof(struct xfs_attrlist) ||
@@ -381,11 +382,9 @@ xfs_ioc_attr_list(
(cursor->hashval || cursor->blkno || cursor->offset))
return -EINVAL;

- /*
- * Check for a properly aligned buffer.
- */
- if (((long)buffer) & (sizeof(int)-1))
- return -EFAULT;
+ buffer = kmem_zalloc_large(bufsize, 0);
+ if (!buffer)
+ return -ENOMEM;

/*
* Initialize the output buffer.
@@ -406,7 +405,13 @@ xfs_ioc_attr_list(
alist->al_offset[0] = context.bufsize;

error = xfs_attr_list(&context);
- ASSERT(error <= 0);
+ if (error)
+ goto out_free;
+
+ if (copy_to_user(ubuf, buffer, bufsize))
+ error = -EFAULT;
+out_free:
+ kmem_free(buffer);
return error;
}

@@ -420,7 +425,6 @@ xfs_attrlist_by_handle(
struct xfs_fsop_attrlist_handlereq __user *p = arg;
xfs_fsop_attrlist_handlereq_t al_hreq;
struct dentry *dentry;
- char *kbuf;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -431,26 +435,15 @@ xfs_attrlist_by_handle(
if (IS_ERR(dentry))
return PTR_ERR(dentry);

- kbuf = kmem_zalloc_large(al_hreq.buflen, 0);
- if (!kbuf)
- goto out_dput;
-
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
- error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), kbuf, al_hreq.buflen,
- al_hreq.flags, cursor);
+ error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
+ al_hreq.buflen, al_hreq.flags, cursor);
if (error)
- goto out_kfree;
-
- if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
- error = -EFAULT;
- goto out_kfree;
- }
+ goto out_dput;

- if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
+ if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t)))
error = -EFAULT;

-out_kfree:
- kmem_free(kbuf);
out_dput:
dput(dentry);
return error;
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index cb7b94c576a7..ec6448b259fb 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -39,7 +39,7 @@ xfs_readlink_by_handle(
int xfs_ioc_attrmulti_one(struct file *parfilp, struct inode *inode,
uint32_t opcode, void __user *uname, void __user *value,
uint32_t *len, uint32_t flags);
-int xfs_ioc_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
+int xfs_ioc_attr_list(struct xfs_inode *dp, void __user *ubuf, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);

extern struct dentry *
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index c11d009a9319..79c9f3c64ce6 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -359,7 +359,6 @@ xfs_compat_attrlist_by_handle(
compat_xfs_fsop_attrlist_handlereq_t __user *p = arg;
compat_xfs_fsop_attrlist_handlereq_t al_hreq;
struct dentry *dentry;
- char *kbuf;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -371,27 +370,16 @@ xfs_compat_attrlist_by_handle(
if (IS_ERR(dentry))
return PTR_ERR(dentry);

- error = -ENOMEM;
- kbuf = kmem_zalloc_large(al_hreq.buflen, 0);
- if (!kbuf)
- goto out_dput;
-
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
- error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), kbuf, al_hreq.buflen,
- al_hreq.flags, cursor);
+ error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)),
+ compat_ptr(al_hreq.buffer), al_hreq.buflen,
+ al_hreq.flags, cursor);
if (error)
- goto out_kfree;
-
- if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
- error = -EFAULT;
- goto out_kfree;
- }
+ goto out_dput;

- if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
+ if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t)))
error = -EFAULT;

-out_kfree:
- kmem_free(kbuf);
out_dput:
dput(dentry);
return error;
--
2.20.1