aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsandeen@sandeen.net <sandeen@sandeen.net>2008-11-25 22:20:06 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-12-02 01:08:01 -0500
commit743bb4650da9e2595d6cedd01c680b5b9398c74a (patch)
treed0bf4740672bdd77a7cd2dde0af7a564fcfe62d6
parent0e446673a15a4e9c336b67c1a638eb12c21d0993 (diff)
[XFS] Move copy_from_user calls out of ioctl helpers into ioctl switch.
Moving the copy_from_user out of some of the ioctl helpers will make it easier for the compat ioctl switch to copy in the right struct, then just pass to the underlying helper. Also, move common access checks into the helpers themselves, and out of the native ioctl switch code, to reduce code duplication between native & compat ioctl callers. Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c109
-rw-r--r--fs/xfs/xfs_dfrag.c8
-rw-r--r--fs/xfs/xfs_dfrag.h2
-rw-r--r--fs/xfs/xfs_fsops.c6
-rw-r--r--fs/xfs/xfs_rtalloc.c2
5 files changed, 63 insertions, 64 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 534b175f3a41..03c55b8fa373 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -71,23 +71,19 @@
71STATIC int 71STATIC int
72xfs_find_handle( 72xfs_find_handle(
73 unsigned int cmd, 73 unsigned int cmd,
74 void __user *arg) 74 xfs_fsop_handlereq_t *hreq)
75{ 75{
76 int hsize; 76 int hsize;
77 xfs_handle_t handle; 77 xfs_handle_t handle;
78 xfs_fsop_handlereq_t hreq;
79 struct inode *inode; 78 struct inode *inode;
80 79
81 if (copy_from_user(&hreq, arg, sizeof(hreq)))
82 return -XFS_ERROR(EFAULT);
83
84 memset((char *)&handle, 0, sizeof(handle)); 80 memset((char *)&handle, 0, sizeof(handle));
85 81
86 switch (cmd) { 82 switch (cmd) {
87 case XFS_IOC_PATH_TO_FSHANDLE: 83 case XFS_IOC_PATH_TO_FSHANDLE:
88 case XFS_IOC_PATH_TO_HANDLE: { 84 case XFS_IOC_PATH_TO_HANDLE: {
89 struct path path; 85 struct path path;
90 int error = user_lpath((const char __user *)hreq.path, &path); 86 int error = user_lpath((const char __user *)hreq->path, &path);
91 if (error) 87 if (error)
92 return error; 88 return error;
93 89
@@ -101,7 +97,7 @@ xfs_find_handle(
101 case XFS_IOC_FD_TO_HANDLE: { 97 case XFS_IOC_FD_TO_HANDLE: {
102 struct file *file; 98 struct file *file;
103 99
104 file = fget(hreq.fd); 100 file = fget(hreq->fd);
105 if (!file) 101 if (!file)
106 return -EBADF; 102 return -EBADF;
107 103
@@ -158,8 +154,8 @@ xfs_find_handle(
158 } 154 }
159 155
160 /* now copy our handle into the user buffer & write out the size */ 156 /* now copy our handle into the user buffer & write out the size */
161 if (copy_to_user(hreq.ohandle, &handle, hsize) || 157 if (copy_to_user(hreq->ohandle, &handle, hsize) ||
162 copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) { 158 copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) {
163 iput(inode); 159 iput(inode);
164 return -XFS_ERROR(EFAULT); 160 return -XFS_ERROR(EFAULT);
165 } 161 }
@@ -252,7 +248,7 @@ xfs_vget_fsop_handlereq(
252STATIC int 248STATIC int
253xfs_open_by_handle( 249xfs_open_by_handle(
254 xfs_mount_t *mp, 250 xfs_mount_t *mp,
255 void __user *arg, 251 xfs_fsop_handlereq_t *hreq,
256 struct file *parfilp, 252 struct file *parfilp,
257 struct inode *parinode) 253 struct inode *parinode)
258{ 254{
@@ -262,14 +258,11 @@ xfs_open_by_handle(
262 struct file *filp; 258 struct file *filp;
263 struct inode *inode; 259 struct inode *inode;
264 struct dentry *dentry; 260 struct dentry *dentry;
265 xfs_fsop_handlereq_t hreq;
266 261
267 if (!capable(CAP_SYS_ADMIN)) 262 if (!capable(CAP_SYS_ADMIN))
268 return -XFS_ERROR(EPERM); 263 return -XFS_ERROR(EPERM);
269 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
270 return -XFS_ERROR(EFAULT);
271 264
272 error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); 265 error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode);
273 if (error) 266 if (error)
274 return -error; 267 return -error;
275 268
@@ -280,10 +273,10 @@ xfs_open_by_handle(
280 } 273 }
281 274
282#if BITS_PER_LONG != 32 275#if BITS_PER_LONG != 32
283 hreq.oflags |= O_LARGEFILE; 276 hreq->oflags |= O_LARGEFILE;
284#endif 277#endif
285 /* Put open permission in namei format. */ 278 /* Put open permission in namei format. */
286 permflag = hreq.oflags; 279 permflag = hreq->oflags;
287 if ((permflag+1) & O_ACCMODE) 280 if ((permflag+1) & O_ACCMODE)
288 permflag++; 281 permflag++;
289 if (permflag & O_TRUNC) 282 if (permflag & O_TRUNC)
@@ -321,7 +314,7 @@ xfs_open_by_handle(
321 mntget(parfilp->f_path.mnt); 314 mntget(parfilp->f_path.mnt);
322 315
323 /* Create file pointer. */ 316 /* Create file pointer. */
324 filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags); 317 filp = dentry_open(dentry, parfilp->f_path.mnt, hreq->oflags);
325 if (IS_ERR(filp)) { 318 if (IS_ERR(filp)) {
326 put_unused_fd(new_fd); 319 put_unused_fd(new_fd);
327 return -XFS_ERROR(-PTR_ERR(filp)); 320 return -XFS_ERROR(-PTR_ERR(filp));
@@ -365,21 +358,18 @@ do_readlink(
365STATIC int 358STATIC int
366xfs_readlink_by_handle( 359xfs_readlink_by_handle(
367 xfs_mount_t *mp, 360 xfs_mount_t *mp,
368 void __user *arg, 361 xfs_fsop_handlereq_t *hreq,
369 struct inode *parinode) 362 struct inode *parinode)
370{ 363{
371 struct inode *inode; 364 struct inode *inode;
372 xfs_fsop_handlereq_t hreq;
373 __u32 olen; 365 __u32 olen;
374 void *link; 366 void *link;
375 int error; 367 int error;
376 368
377 if (!capable(CAP_SYS_ADMIN)) 369 if (!capable(CAP_SYS_ADMIN))
378 return -XFS_ERROR(EPERM); 370 return -XFS_ERROR(EPERM);
379 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
380 return -XFS_ERROR(EFAULT);
381 371
382 error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); 372 error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode);
383 if (error) 373 if (error)
384 return -error; 374 return -error;
385 375
@@ -389,7 +379,7 @@ xfs_readlink_by_handle(
389 goto out_iput; 379 goto out_iput;
390 } 380 }
391 381
392 if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { 382 if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
393 error = -XFS_ERROR(EFAULT); 383 error = -XFS_ERROR(EFAULT);
394 goto out_iput; 384 goto out_iput;
395 } 385 }
@@ -401,7 +391,7 @@ xfs_readlink_by_handle(
401 error = -xfs_readlink(XFS_I(inode), link); 391 error = -xfs_readlink(XFS_I(inode), link);
402 if (error) 392 if (error)
403 goto out_kfree; 393 goto out_kfree;
404 error = do_readlink(hreq.ohandle, olen, link); 394 error = do_readlink(hreq->ohandle, olen, link);
405 if (error) 395 if (error)
406 goto out_kfree; 396 goto out_kfree;
407 397
@@ -668,12 +658,19 @@ xfs_ioc_space(
668 struct file *filp, 658 struct file *filp,
669 int ioflags, 659 int ioflags,
670 unsigned int cmd, 660 unsigned int cmd,
671 void __user *arg) 661 xfs_flock64_t *bf)
672{ 662{
673 xfs_flock64_t bf;
674 int attr_flags = 0; 663 int attr_flags = 0;
675 int error; 664 int error;
676 665
666 /*
667 * Only allow the sys admin to reserve space unless
668 * unwritten extents are enabled.
669 */
670 if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) &&
671 !capable(CAP_SYS_ADMIN))
672 return -XFS_ERROR(EPERM);
673
677 if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) 674 if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
678 return -XFS_ERROR(EPERM); 675 return -XFS_ERROR(EPERM);
679 676
@@ -683,15 +680,12 @@ xfs_ioc_space(
683 if (!S_ISREG(inode->i_mode)) 680 if (!S_ISREG(inode->i_mode))
684 return -XFS_ERROR(EINVAL); 681 return -XFS_ERROR(EINVAL);
685 682
686 if (copy_from_user(&bf, arg, sizeof(bf)))
687 return -XFS_ERROR(EFAULT);
688
689 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 683 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
690 attr_flags |= XFS_ATTR_NONBLOCK; 684 attr_flags |= XFS_ATTR_NONBLOCK;
691 if (ioflags & IO_INVIS) 685 if (ioflags & IO_INVIS)
692 attr_flags |= XFS_ATTR_DMI; 686 attr_flags |= XFS_ATTR_DMI;
693 687
694 error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos, attr_flags); 688 error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
695 return -error; 689 return -error;
696} 690}
697 691
@@ -1356,17 +1350,13 @@ xfs_ioctl(
1356 case XFS_IOC_ALLOCSP64: 1350 case XFS_IOC_ALLOCSP64:
1357 case XFS_IOC_FREESP64: 1351 case XFS_IOC_FREESP64:
1358 case XFS_IOC_RESVSP64: 1352 case XFS_IOC_RESVSP64:
1359 case XFS_IOC_UNRESVSP64: 1353 case XFS_IOC_UNRESVSP64: {
1360 /* 1354 xfs_flock64_t bf;
1361 * Only allow the sys admin to reserve space unless
1362 * unwritten extents are enabled.
1363 */
1364 if (!xfs_sb_version_hasextflgbit(&mp->m_sb) &&
1365 !capable(CAP_SYS_ADMIN))
1366 return -EPERM;
1367
1368 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
1369 1355
1356 if (copy_from_user(&bf, arg, sizeof(bf)))
1357 return -XFS_ERROR(EFAULT);
1358 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
1359 }
1370 case XFS_IOC_DIOINFO: { 1360 case XFS_IOC_DIOINFO: {
1371 struct dioattr da; 1361 struct dioattr da;
1372 xfs_buftarg_t *target = 1362 xfs_buftarg_t *target =
@@ -1426,18 +1416,30 @@ xfs_ioctl(
1426 1416
1427 case XFS_IOC_FD_TO_HANDLE: 1417 case XFS_IOC_FD_TO_HANDLE:
1428 case XFS_IOC_PATH_TO_HANDLE: 1418 case XFS_IOC_PATH_TO_HANDLE:
1429 case XFS_IOC_PATH_TO_FSHANDLE: 1419 case XFS_IOC_PATH_TO_FSHANDLE: {
1430 return xfs_find_handle(cmd, arg); 1420 xfs_fsop_handlereq_t hreq;
1431 1421
1432 case XFS_IOC_OPEN_BY_HANDLE: 1422 if (copy_from_user(&hreq, arg, sizeof(hreq)))
1433 return xfs_open_by_handle(mp, arg, filp, inode); 1423 return -XFS_ERROR(EFAULT);
1424 return xfs_find_handle(cmd, &hreq);
1425 }
1426 case XFS_IOC_OPEN_BY_HANDLE: {
1427 xfs_fsop_handlereq_t hreq;
1434 1428
1429 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1430 return -XFS_ERROR(EFAULT);
1431 return xfs_open_by_handle(mp, &hreq, filp, inode);
1432 }
1435 case XFS_IOC_FSSETDM_BY_HANDLE: 1433 case XFS_IOC_FSSETDM_BY_HANDLE:
1436 return xfs_fssetdm_by_handle(mp, arg, inode); 1434 return xfs_fssetdm_by_handle(mp, arg, inode);
1437 1435
1438 case XFS_IOC_READLINK_BY_HANDLE: 1436 case XFS_IOC_READLINK_BY_HANDLE: {
1439 return xfs_readlink_by_handle(mp, arg, inode); 1437 xfs_fsop_handlereq_t hreq;
1440 1438
1439 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1440 return -XFS_ERROR(EFAULT);
1441 return xfs_readlink_by_handle(mp, &hreq, inode);
1442 }
1441 case XFS_IOC_ATTRLIST_BY_HANDLE: 1443 case XFS_IOC_ATTRLIST_BY_HANDLE:
1442 return xfs_attrlist_by_handle(mp, arg, inode); 1444 return xfs_attrlist_by_handle(mp, arg, inode);
1443 1445
@@ -1445,7 +1447,11 @@ xfs_ioctl(
1445 return xfs_attrmulti_by_handle(mp, arg, filp, inode); 1447 return xfs_attrmulti_by_handle(mp, arg, filp, inode);
1446 1448
1447 case XFS_IOC_SWAPEXT: { 1449 case XFS_IOC_SWAPEXT: {
1448 error = xfs_swapext((struct xfs_swapext __user *)arg); 1450 struct xfs_swapext sxp;
1451
1452 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1453 return -XFS_ERROR(EFAULT);
1454 error = xfs_swapext(&sxp);
1449 return -error; 1455 return -error;
1450 } 1456 }
1451 1457
@@ -1501,9 +1507,6 @@ xfs_ioctl(
1501 case XFS_IOC_FSGROWFSDATA: { 1507 case XFS_IOC_FSGROWFSDATA: {
1502 xfs_growfs_data_t in; 1508 xfs_growfs_data_t in;
1503 1509
1504 if (!capable(CAP_SYS_ADMIN))
1505 return -EPERM;
1506
1507 if (copy_from_user(&in, arg, sizeof(in))) 1510 if (copy_from_user(&in, arg, sizeof(in)))
1508 return -XFS_ERROR(EFAULT); 1511 return -XFS_ERROR(EFAULT);
1509 1512
@@ -1514,9 +1517,6 @@ xfs_ioctl(
1514 case XFS_IOC_FSGROWFSLOG: { 1517 case XFS_IOC_FSGROWFSLOG: {
1515 xfs_growfs_log_t in; 1518 xfs_growfs_log_t in;
1516 1519
1517 if (!capable(CAP_SYS_ADMIN))
1518 return -EPERM;
1519
1520 if (copy_from_user(&in, arg, sizeof(in))) 1520 if (copy_from_user(&in, arg, sizeof(in)))
1521 return -XFS_ERROR(EFAULT); 1521 return -XFS_ERROR(EFAULT);
1522 1522
@@ -1527,9 +1527,6 @@ xfs_ioctl(
1527 case XFS_IOC_FSGROWFSRT: { 1527 case XFS_IOC_FSGROWFSRT: {
1528 xfs_growfs_rt_t in; 1528 xfs_growfs_rt_t in;
1529 1529
1530 if (!capable(CAP_SYS_ADMIN))
1531 return -EPERM;
1532
1533 if (copy_from_user(&in, arg, sizeof(in))) 1530 if (copy_from_user(&in, arg, sizeof(in)))
1534 return -XFS_ERROR(EFAULT); 1531 return -XFS_ERROR(EFAULT);
1535 1532
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 75b0cd4da0ea..b4c1ee713492 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -49,9 +49,8 @@
49 */ 49 */
50int 50int
51xfs_swapext( 51xfs_swapext(
52 xfs_swapext_t __user *sxu) 52 xfs_swapext_t *sxp)
53{ 53{
54 xfs_swapext_t *sxp;
55 xfs_inode_t *ip, *tip; 54 xfs_inode_t *ip, *tip;
56 struct file *file, *target_file; 55 struct file *file, *target_file;
57 int error = 0; 56 int error = 0;
@@ -62,11 +61,6 @@ xfs_swapext(
62 goto out; 61 goto out;
63 } 62 }
64 63
65 if (copy_from_user(sxp, sxu, sizeof(xfs_swapext_t))) {
66 error = XFS_ERROR(EFAULT);
67 goto out_free_sxp;
68 }
69
70 /* Pull information for the target fd */ 64 /* Pull information for the target fd */
71 file = fget((int)sxp->sx_fdtarget); 65 file = fget((int)sxp->sx_fdtarget);
72 if (!file) { 66 if (!file) {
diff --git a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h
index da178205be68..4f55a6306558 100644
--- a/fs/xfs/xfs_dfrag.h
+++ b/fs/xfs/xfs_dfrag.h
@@ -46,7 +46,7 @@ typedef struct xfs_swapext
46/* 46/*
47 * Syscall interface for xfs_swapext 47 * Syscall interface for xfs_swapext
48 */ 48 */
49int xfs_swapext(struct xfs_swapext __user *sx); 49int xfs_swapext(struct xfs_swapext *sx);
50 50
51int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip, 51int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
52 struct xfs_swapext *sxp); 52 struct xfs_swapext *sxp);
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index f1d0585041b9..852b6d32e8d0 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -435,6 +435,9 @@ xfs_growfs_data(
435 xfs_growfs_data_t *in) 435 xfs_growfs_data_t *in)
436{ 436{
437 int error; 437 int error;
438
439 if (!capable(CAP_SYS_ADMIN))
440 return XFS_ERROR(EPERM);
438 if (!mutex_trylock(&mp->m_growlock)) 441 if (!mutex_trylock(&mp->m_growlock))
439 return XFS_ERROR(EWOULDBLOCK); 442 return XFS_ERROR(EWOULDBLOCK);
440 error = xfs_growfs_data_private(mp, in); 443 error = xfs_growfs_data_private(mp, in);
@@ -448,6 +451,9 @@ xfs_growfs_log(
448 xfs_growfs_log_t *in) 451 xfs_growfs_log_t *in)
449{ 452{
450 int error; 453 int error;
454
455 if (!capable(CAP_SYS_ADMIN))
456 return XFS_ERROR(EPERM);
451 if (!mutex_trylock(&mp->m_growlock)) 457 if (!mutex_trylock(&mp->m_growlock))
452 return XFS_ERROR(EWOULDBLOCK); 458 return XFS_ERROR(EWOULDBLOCK);
453 error = xfs_growfs_log_private(mp, in); 459 error = xfs_growfs_log_private(mp, in);
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index f18b9b281799..edf12c7b834c 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1876,6 +1876,8 @@ xfs_growfs_rt(
1876 /* 1876 /*
1877 * Initial error checking. 1877 * Initial error checking.
1878 */ 1878 */
1879 if (!capable(CAP_SYS_ADMIN))
1880 return XFS_ERROR(EPERM);
1879 if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL || 1881 if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
1880 (nrblocks = in->newblocks) <= sbp->sb_rblocks || 1882 (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
1881 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize))) 1883 (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))