xfs: lift cursor copy in/out into xfs_ioc_attr_list
Lift the common code to copy the cursor from and to user space into
xfs_ioc_attr_list. Note that this means we copy in twice now as
the cursor is in the middle of the conaining structure, but we never
touch the memory for the original copy. Doing so keeps the cursor
handling isolated in the common helper.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 34f5969..2a7d059 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -355,9 +355,10 @@ xfs_ioc_attr_list(
void __user *ubuf,
int bufsize,
int flags,
- struct attrlist_cursor_kern *cursor)
+ struct xfs_attrlist_cursor __user *ucursor)
{
struct xfs_attr_list_context context;
+ struct attrlist_cursor_kern cursor;
struct xfs_attrlist *alist;
void *buffer;
int error;
@@ -377,10 +378,12 @@ xfs_ioc_attr_list(
/*
* Validate the cursor.
*/
- if (cursor->pad1 || cursor->pad2)
+ if (copy_from_user(&cursor, ucursor, sizeof(cursor)))
+ return -EFAULT;
+ if (cursor.pad1 || cursor.pad2)
return -EINVAL;
- if ((cursor->initted == 0) &&
- (cursor->hashval || cursor->blkno || cursor->offset))
+ if ((cursor.initted == 0) &&
+ (cursor.hashval || cursor.blkno || cursor.offset))
return -EINVAL;
buffer = kmem_zalloc_large(bufsize, 0);
@@ -392,7 +395,7 @@ xfs_ioc_attr_list(
*/
memset(&context, 0, sizeof(context));
context.dp = dp;
- context.cursor = cursor;
+ context.cursor = &cursor;
context.resynch = 1;
context.flags = flags;
context.buffer = buffer;
@@ -409,7 +412,8 @@ xfs_ioc_attr_list(
if (error)
goto out_free;
- if (copy_to_user(ubuf, buffer, bufsize))
+ if (copy_to_user(ubuf, buffer, bufsize) ||
+ copy_to_user(ucursor, &cursor, sizeof(cursor)))
error = -EFAULT;
out_free:
kmem_free(buffer);
@@ -419,33 +423,23 @@ xfs_ioc_attr_list(
STATIC int
xfs_attrlist_by_handle(
struct file *parfilp,
- void __user *arg)
+ struct xfs_fsop_attrlist_handlereq __user *p)
{
- int error = -ENOMEM;
- attrlist_cursor_kern_t *cursor;
- struct xfs_fsop_attrlist_handlereq __user *p = arg;
- xfs_fsop_attrlist_handlereq_t al_hreq;
+ struct xfs_fsop_attrlist_handlereq al_hreq;
struct dentry *dentry;
+ int error = -ENOMEM;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
+ if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
return -EFAULT;
dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
- cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
- al_hreq.buflen, al_hreq.flags, cursor);
- if (error)
- goto out_dput;
-
- if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t)))
- error = -EFAULT;
-
-out_dput:
+ al_hreq.buflen, al_hreq.flags, &p->pos);
dput(dentry);
return error;
}