2018-06-06 05:42:14 +03:00
// SPDX-License-Identifier: GPL-2.0
2005-04-17 02:20:36 +04:00
/*
2005-11-02 06:58:39 +03:00
* Copyright ( c ) 2004 - 2005 Silicon Graphics , Inc .
* All Rights Reserved .
2005-04-17 02:20:36 +04:00
*/
2009-01-19 04:03:03 +03:00
# include <linux/mount.h>
2017-03-29 00:56:37 +03:00
# include <linux/fsmap.h>
2005-04-17 02:20:36 +04:00
# include "xfs.h"
# include "xfs_fs.h"
2019-06-29 05:25:35 +03:00
# include "xfs_shared.h"
2013-10-23 03:51:50 +04:00
# include "xfs_format.h"
2013-10-23 03:50:10 +04:00
# include "xfs_log_format.h"
# include "xfs_trans_resv.h"
2007-07-11 05:10:19 +04:00
# include "xfs_mount.h"
# include "xfs_inode.h"
2019-07-02 19:39:40 +03:00
# include "xfs_iwalk.h"
2007-07-11 05:10:19 +04:00
# include "xfs_itable.h"
2008-11-26 06:20:08 +03:00
# include "xfs_fsops.h"
2008-11-26 06:20:10 +03:00
# include "xfs_rtalloc.h"
2008-11-26 06:20:14 +03:00
# include "xfs_attr.h"
2008-11-26 06:20:08 +03:00
# include "xfs_ioctl.h"
2007-11-23 08:28:09 +03:00
# include "xfs_ioctl32.h"
2009-12-15 02:14:59 +03:00
# include "xfs_trace.h"
2018-01-08 21:51:27 +03:00
# include "xfs_sb.h"
2005-04-17 02:20:36 +04:00
2005-09-05 02:25:06 +04:00
# define _NATIVE_IOC(cmd, type) \
_IOC ( _IOC_DIR ( cmd ) , _IOC_TYPE ( cmd ) , _IOC_NR ( cmd ) , sizeof ( type ) )
2008-11-26 06:20:07 +03:00
# ifdef BROKEN_X86_ALIGNMENT
2008-11-26 06:20:08 +03:00
STATIC int
xfs_compat_flock64_copyin (
xfs_flock64_t * bf ,
compat_xfs_flock64_t __user * arg32 )
2005-09-05 02:25:06 +04:00
{
2008-11-26 06:20:08 +03:00
if ( get_user ( bf - > l_type , & arg32 - > l_type ) | |
get_user ( bf - > l_whence , & arg32 - > l_whence ) | |
get_user ( bf - > l_start , & arg32 - > l_start ) | |
get_user ( bf - > l_len , & arg32 - > l_len ) | |
get_user ( bf - > l_sysid , & arg32 - > l_sysid ) | |
get_user ( bf - > l_pid , & arg32 - > l_pid ) | |
copy_from_user ( bf - > l_pad , & arg32 - > l_pad , 4 * sizeof ( u32 ) ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:08 +03:00
return 0 ;
2005-09-05 02:25:06 +04:00
}
2008-11-26 06:20:08 +03:00
STATIC int
xfs_compat_ioc_fsgeometry_v1 (
struct xfs_mount * mp ,
compat_xfs_fsop_geom_v1_t __user * arg32 )
2007-07-11 05:09:57 +04:00
{
2019-04-12 17:41:16 +03:00
struct xfs_fsop_geom fsgeo ;
2007-07-11 05:09:57 +04:00
2019-05-02 06:26:30 +03:00
xfs_fs_geometry ( & mp - > m_sb , & fsgeo , 3 ) ;
2008-11-26 06:20:08 +03:00
/* The 32-bit variant simply has some padding at the end */
if ( copy_to_user ( arg32 , & fsgeo , sizeof ( struct compat_xfs_fsop_geom_v1 ) ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:08 +03:00
return 0 ;
2007-07-11 05:09:57 +04:00
}
2008-11-26 06:20:10 +03:00
STATIC int
xfs_compat_growfs_data_copyin (
struct xfs_growfs_data * in ,
compat_xfs_growfs_data_t __user * arg32 )
{
if ( get_user ( in - > newblocks , & arg32 - > newblocks ) | |
get_user ( in - > imaxpct , & arg32 - > imaxpct ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:10 +03:00
return 0 ;
}
STATIC int
xfs_compat_growfs_rt_copyin (
struct xfs_growfs_rt * in ,
compat_xfs_growfs_rt_t __user * arg32 )
{
if ( get_user ( in - > newblocks , & arg32 - > newblocks ) | |
get_user ( in - > extsize , & arg32 - > extsize ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:10 +03:00
return 0 ;
}
2008-11-26 06:20:08 +03:00
STATIC int
2019-07-04 06:36:26 +03:00
xfs_fsinumbers_fmt_compat (
2019-07-04 06:36:27 +03:00
struct xfs_ibulk * breq ,
const struct xfs_inumbers * ig )
2007-07-11 05:10:19 +04:00
{
2019-07-04 06:36:27 +03:00
struct compat_xfs_inogrp __user * p32 = breq - > ubuffer ;
struct xfs_inogrp ig1 ;
struct xfs_inogrp * igrp = & ig1 ;
xfs_inumbers_to_inogrp ( & ig1 , ig ) ;
2007-07-11 05:10:19 +04:00
2019-07-02 19:39:43 +03:00
if ( put_user ( igrp - > xi_startino , & p32 - > xi_startino ) | |
put_user ( igrp - > xi_alloccount , & p32 - > xi_alloccount ) | |
put_user ( igrp - > xi_allocmask , & p32 - > xi_allocmask ) )
return - EFAULT ;
return xfs_ibulk_advance ( breq , sizeof ( struct compat_xfs_inogrp ) ) ;
2007-07-11 05:10:19 +04:00
}
2005-04-17 02:20:36 +04:00
# else
2019-07-04 06:36:26 +03:00
# define xfs_fsinumbers_fmt_compat xfs_fsinumbers_fmt
2008-11-26 06:20:17 +03:00
# endif /* BROKEN_X86_ALIGNMENT */
2007-07-11 05:10:19 +04:00
2008-11-26 06:20:09 +03:00
STATIC int
xfs_ioctl32_bstime_copyin (
xfs_bstime_t * bstime ,
compat_xfs_bstime_t __user * bstime32 )
{
2020-01-03 00:27:44 +03:00
old_time32_t sec32 ; /* tv_sec differs on 64 vs. 32 */
2008-11-26 06:20:09 +03:00
if ( get_user ( sec32 , & bstime32 - > tv_sec ) | |
get_user ( bstime - > tv_nsec , & bstime32 - > tv_nsec ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:09 +03:00
bstime - > tv_sec = sec32 ;
return 0 ;
}
2019-07-04 06:36:25 +03:00
/*
* struct xfs_bstat has differing alignment on intel , & bstime_t sizes
* everywhere
*/
2008-11-26 06:20:09 +03:00
STATIC int
xfs_ioctl32_bstat_copyin (
2019-07-04 06:36:25 +03:00
struct xfs_bstat * bstat ,
struct compat_xfs_bstat __user * bstat32 )
2008-11-26 06:20:09 +03:00
{
if ( get_user ( bstat - > bs_ino , & bstat32 - > bs_ino ) | |
get_user ( bstat - > bs_mode , & bstat32 - > bs_mode ) | |
get_user ( bstat - > bs_nlink , & bstat32 - > bs_nlink ) | |
get_user ( bstat - > bs_uid , & bstat32 - > bs_uid ) | |
get_user ( bstat - > bs_gid , & bstat32 - > bs_gid ) | |
get_user ( bstat - > bs_rdev , & bstat32 - > bs_rdev ) | |
get_user ( bstat - > bs_blksize , & bstat32 - > bs_blksize ) | |
get_user ( bstat - > bs_size , & bstat32 - > bs_size ) | |
xfs_ioctl32_bstime_copyin ( & bstat - > bs_atime , & bstat32 - > bs_atime ) | |
xfs_ioctl32_bstime_copyin ( & bstat - > bs_mtime , & bstat32 - > bs_mtime ) | |
xfs_ioctl32_bstime_copyin ( & bstat - > bs_ctime , & bstat32 - > bs_ctime ) | |
get_user ( bstat - > bs_blocks , & bstat32 - > bs_size ) | |
get_user ( bstat - > bs_xflags , & bstat32 - > bs_size ) | |
get_user ( bstat - > bs_extsize , & bstat32 - > bs_extsize ) | |
get_user ( bstat - > bs_extents , & bstat32 - > bs_extents ) | |
get_user ( bstat - > bs_gen , & bstat32 - > bs_gen ) | |
2010-09-26 10:10:18 +04:00
get_user ( bstat - > bs_projid_lo , & bstat32 - > bs_projid_lo ) | |
get_user ( bstat - > bs_projid_hi , & bstat32 - > bs_projid_hi ) | |
2014-10-02 03:17:58 +04:00
get_user ( bstat - > bs_forkoff , & bstat32 - > bs_forkoff ) | |
2008-11-26 06:20:09 +03:00
get_user ( bstat - > bs_dmevmask , & bstat32 - > bs_dmevmask ) | |
get_user ( bstat - > bs_dmstate , & bstat32 - > bs_dmstate ) | |
get_user ( bstat - > bs_aextents , & bstat32 - > bs_aextents ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:09 +03:00
return 0 ;
}
2007-07-11 05:10:19 +04:00
/* XFS_IOC_FSBULKSTAT and friends */
2008-11-26 06:20:08 +03:00
STATIC int
xfs_bstime_store_compat (
compat_xfs_bstime_t __user * p32 ,
const xfs_bstime_t * p )
2007-07-11 05:10:19 +04:00
{
2008-11-26 06:20:08 +03:00
__s32 sec32 ;
2007-07-11 05:10:19 +04:00
sec32 = p - > tv_sec ;
if ( put_user ( sec32 , & p32 - > tv_sec ) | |
put_user ( p - > tv_nsec , & p32 - > tv_nsec ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
return 0 ;
}
2008-11-26 06:20:12 +03:00
/* Return 0 on success or positive error (to xfs_bulkstat()) */
2008-11-26 06:20:08 +03:00
STATIC int
2019-07-04 06:36:26 +03:00
xfs_fsbulkstat_one_fmt_compat (
2019-07-04 06:36:26 +03:00
struct xfs_ibulk * breq ,
const struct xfs_bulkstat * bstat )
2007-07-11 05:10:19 +04:00
{
2019-07-04 06:36:26 +03:00
struct compat_xfs_bstat __user * p32 = breq - > ubuffer ;
struct xfs_bstat bs1 ;
struct xfs_bstat * buffer = & bs1 ;
xfs_bulkstat_to_bstat ( breq - > mp , & bs1 , bstat ) ;
2008-11-26 06:20:12 +03:00
if ( put_user ( buffer - > bs_ino , & p32 - > bs_ino ) | |
put_user ( buffer - > bs_mode , & p32 - > bs_mode ) | |
put_user ( buffer - > bs_nlink , & p32 - > bs_nlink ) | |
put_user ( buffer - > bs_uid , & p32 - > bs_uid ) | |
put_user ( buffer - > bs_gid , & p32 - > bs_gid ) | |
put_user ( buffer - > bs_rdev , & p32 - > bs_rdev ) | |
put_user ( buffer - > bs_blksize , & p32 - > bs_blksize ) | |
put_user ( buffer - > bs_size , & p32 - > bs_size ) | |
2007-07-11 05:10:19 +04:00
xfs_bstime_store_compat ( & p32 - > bs_atime , & buffer - > bs_atime ) | |
xfs_bstime_store_compat ( & p32 - > bs_mtime , & buffer - > bs_mtime ) | |
xfs_bstime_store_compat ( & p32 - > bs_ctime , & buffer - > bs_ctime ) | |
2008-11-26 06:20:12 +03:00
put_user ( buffer - > bs_blocks , & p32 - > bs_blocks ) | |
put_user ( buffer - > bs_xflags , & p32 - > bs_xflags ) | |
put_user ( buffer - > bs_extsize , & p32 - > bs_extsize ) | |
put_user ( buffer - > bs_extents , & p32 - > bs_extents ) | |
put_user ( buffer - > bs_gen , & p32 - > bs_gen ) | |
put_user ( buffer - > bs_projid , & p32 - > bs_projid ) | |
2010-09-26 10:10:18 +04:00
put_user ( buffer - > bs_projid_hi , & p32 - > bs_projid_hi ) | |
2014-10-02 03:17:58 +04:00
put_user ( buffer - > bs_forkoff , & p32 - > bs_forkoff ) | |
2008-11-26 06:20:12 +03:00
put_user ( buffer - > bs_dmevmask , & p32 - > bs_dmevmask ) | |
put_user ( buffer - > bs_dmstate , & p32 - > bs_dmstate ) | |
2007-07-11 05:10:19 +04:00
put_user ( buffer - > bs_aextents , & p32 - > bs_aextents ) )
2014-06-25 08:58:08 +04:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
2019-07-02 19:39:40 +03:00
return xfs_ibulk_advance ( breq , sizeof ( struct compat_xfs_bstat ) ) ;
2008-11-26 06:20:11 +03:00
}
2007-07-11 05:10:19 +04:00
/* copied from xfs_ioctl.c */
STATIC int
2019-07-04 06:36:26 +03:00
xfs_compat_ioc_fsbulkstat (
2008-11-26 06:20:11 +03:00
xfs_mount_t * mp ,
unsigned int cmd ,
2019-07-04 06:36:25 +03:00
struct compat_xfs_fsop_bulkreq __user * p32 )
2005-04-17 02:20:36 +04:00
{
u32 addr ;
2019-07-02 19:39:40 +03:00
struct xfs_fsop_bulkreq bulkreq ;
struct xfs_ibulk breq = {
. mp = mp ,
. ocount = 0 ,
} ;
xfs_ino_t lastino ;
2007-07-11 05:10:19 +04:00
int error ;
2018-12-17 20:35:27 +03:00
/*
* Output structure handling functions . Depending on the command ,
* either the xfs_bstat and xfs_inogrp structures are written out
* to userpace memory via bulkreq . ubuffer . Normally the compat
* functions and structure size are the correct ones to use . . .
*/
2019-07-04 06:36:26 +03:00
inumbers_fmt_pf inumbers_func = xfs_fsinumbers_fmt_compat ;
bulkstat_one_fmt_pf bs_one_func = xfs_fsbulkstat_one_fmt_compat ;
2018-12-17 20:35:27 +03:00
# ifdef CONFIG_X86_X32
if ( in_x32_syscall ( ) ) {
/*
* . . . but on x32 the input xfs_fsop_bulkreq has pointers
* which must be handled in the " compat " ( 32 - bit ) way , while
* the xfs_bstat and xfs_inogrp structures follow native 64 -
* bit layout convention . So adjust accordingly , otherwise
* the data written out in compat layout will not match what
* x32 userspace expects .
*/
2019-07-04 06:36:26 +03:00
inumbers_func = xfs_fsinumbers_fmt ;
bs_one_func = xfs_fsbulkstat_one_fmt ;
2018-12-17 20:35:27 +03:00
}
# endif
2007-07-11 05:10:19 +04:00
/* done = 1 if there are more stats to get and if bulkstat */
/* should be called again (unused here, but used in dmapi) */
2005-04-17 02:20:36 +04:00
2007-07-11 05:10:19 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
2014-06-22 09:04:54 +04:00
return - EPERM ;
2007-07-11 05:10:19 +04:00
if ( XFS_FORCED_SHUTDOWN ( mp ) )
2014-06-22 09:04:54 +04:00
return - EIO ;
2007-07-11 05:10:19 +04:00
if ( get_user ( addr , & p32 - > lastip ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
bulkreq . lastip = compat_ptr ( addr ) ;
if ( get_user ( bulkreq . icount , & p32 - > icount ) | |
get_user ( addr , & p32 - > ubuffer ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
bulkreq . ubuffer = compat_ptr ( addr ) ;
if ( get_user ( addr , & p32 - > ocount ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
bulkreq . ocount = compat_ptr ( addr ) ;
2005-04-17 02:20:36 +04:00
2019-07-02 19:39:40 +03:00
if ( copy_from_user ( & lastino , bulkreq . lastip , sizeof ( __s64 ) ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
2019-07-02 19:39:40 +03:00
if ( bulkreq . icount < = 0 )
2014-06-22 09:04:54 +04:00
return - EINVAL ;
2007-07-11 05:10:19 +04:00
2007-11-23 08:30:32 +03:00
if ( bulkreq . ubuffer = = NULL )
2014-06-22 09:04:54 +04:00
return - EINVAL ;
2007-11-23 08:30:32 +03:00
2019-07-02 19:39:40 +03:00
breq . ubuffer = bulkreq . ubuffer ;
breq . icount = bulkreq . icount ;
/*
* FSBULKSTAT_SINGLE expects that * lastip contains the inode number
* that we want to stat . However , FSINUMBERS and FSBULKSTAT expect
* that * lastip contains either zero or the number of the last inode to
* be examined by the previous call and return results starting with
* the next inode after that . The new bulk request back end functions
* take the inode to start with , so we have to compute the startino
* parameter from lastino to maintain correct function . lastino = = 0
* is a special case because it has traditionally meant " first inode
* in filesystem " .
*/
2008-11-26 06:20:13 +03:00
if ( cmd = = XFS_IOC_FSINUMBERS_32 ) {
2019-07-02 19:39:43 +03:00
breq . startino = lastino ? lastino + 1 : 0 ;
error = xfs_inumbers ( & breq , inumbers_func ) ;
lastino = breq . startino - 1 ;
2008-11-26 06:20:13 +03:00
} else if ( cmd = = XFS_IOC_FSBULKSTAT_SINGLE_32 ) {
2019-07-02 19:39:40 +03:00
breq . startino = lastino ;
breq . icount = 1 ;
error = xfs_bulkstat_one ( & breq , bs_one_func ) ;
lastino = breq . startino ;
2008-11-26 06:20:13 +03:00
} else if ( cmd = = XFS_IOC_FSBULKSTAT_32 ) {
2019-07-02 19:39:40 +03:00
breq . startino = lastino ? lastino + 1 : 0 ;
error = xfs_bulkstat ( & breq , bs_one_func ) ;
lastino = breq . startino - 1 ;
} else {
2014-06-25 08:58:08 +04:00
error = - EINVAL ;
2019-07-02 19:39:40 +03:00
}
2007-07-11 05:10:19 +04:00
if ( error )
2014-06-25 08:58:08 +04:00
return error ;
2007-07-11 05:10:19 +04:00
2019-07-02 19:39:39 +03:00
if ( bulkreq . lastip ! = NULL & &
2019-07-02 19:39:40 +03:00
copy_to_user ( bulkreq . lastip , & lastino , sizeof ( xfs_ino_t ) ) )
2019-07-02 19:39:39 +03:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
2019-07-02 19:39:39 +03:00
if ( bulkreq . ocount ! = NULL & &
2019-07-02 19:39:40 +03:00
copy_to_user ( bulkreq . ocount , & breq . ocount , sizeof ( __s32 ) ) )
2019-07-02 19:39:39 +03:00
return - EFAULT ;
2007-07-11 05:10:19 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-07-11 05:10:19 +04:00
2008-11-26 06:20:08 +03:00
STATIC int
xfs_compat_handlereq_copyin (
xfs_fsop_handlereq_t * hreq ,
compat_xfs_fsop_handlereq_t __user * arg32 )
2007-07-11 05:10:09 +04:00
{
2008-11-26 06:20:08 +03:00
compat_xfs_fsop_handlereq_t hreq32 ;
if ( copy_from_user ( & hreq32 , arg32 , sizeof ( compat_xfs_fsop_handlereq_t ) ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:08 +03:00
hreq - > fd = hreq32 . fd ;
hreq - > path = compat_ptr ( hreq32 . path ) ;
hreq - > oflags = hreq32 . oflags ;
hreq - > ihandle = compat_ptr ( hreq32 . ihandle ) ;
hreq - > ihandlen = hreq32 . ihandlen ;
hreq - > ohandle = compat_ptr ( hreq32 . ohandle ) ;
hreq - > ohandlen = compat_ptr ( hreq32 . ohandlen ) ;
return 0 ;
2007-07-11 05:10:09 +04:00
}
2009-01-19 04:02:57 +03:00
STATIC struct dentry *
xfs_compat_handlereq_to_dentry (
struct file * parfilp ,
compat_xfs_fsop_handlereq_t * hreq )
2008-11-26 06:20:14 +03:00
{
2009-01-19 04:02:57 +03:00
return xfs_handle_to_dentry ( parfilp ,
compat_ptr ( hreq - > ihandle ) , hreq - > ihandlen ) ;
2008-11-26 06:20:14 +03:00
}
STATIC int
xfs_compat_attrlist_by_handle (
2009-01-19 04:02:57 +03:00
struct file * parfilp ,
2020-02-27 04:30:41 +03:00
compat_xfs_fsop_attrlist_handlereq_t __user * p )
2008-11-26 06:20:14 +03:00
{
compat_xfs_fsop_attrlist_handlereq_t al_hreq ;
2009-01-19 04:02:57 +03:00
struct dentry * dentry ;
2020-02-27 04:30:41 +03:00
int error ;
2008-11-26 06:20:14 +03:00
if ( ! capable ( CAP_SYS_ADMIN ) )
2014-06-22 09:04:54 +04:00
return - EPERM ;
2020-02-27 04:30:41 +03:00
if ( copy_from_user ( & al_hreq , p , sizeof ( al_hreq ) ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:14 +03:00
2009-01-19 04:02:57 +03:00
dentry = xfs_compat_handlereq_to_dentry ( parfilp , & al_hreq . hreq ) ;
if ( IS_ERR ( dentry ) )
return PTR_ERR ( dentry ) ;
2008-11-26 06:20:14 +03:00
2020-02-27 04:30:40 +03:00
error = xfs_ioc_attr_list ( XFS_I ( d_inode ( dentry ) ) ,
compat_ptr ( al_hreq . buffer ) , al_hreq . buflen ,
2020-02-27 04:30:41 +03:00
al_hreq . flags , & p - > pos ) ;
2009-01-19 04:02:57 +03:00
dput ( dentry ) ;
return error ;
2008-11-26 06:20:14 +03:00
}
2008-11-26 06:20:15 +03:00
STATIC int
xfs_compat_attrmulti_by_handle (
2009-01-19 04:02:57 +03:00
struct file * parfilp ,
void __user * arg )
2008-11-26 06:20:15 +03:00
{
int error ;
compat_xfs_attr_multiop_t * ops ;
compat_xfs_fsop_attrmulti_handlereq_t am_hreq ;
2009-01-19 04:02:57 +03:00
struct dentry * dentry ;
2008-11-26 06:20:15 +03:00
unsigned int i , size ;
if ( ! capable ( CAP_SYS_ADMIN ) )
2014-06-22 09:04:54 +04:00
return - EPERM ;
2008-11-26 06:20:15 +03:00
if ( copy_from_user ( & am_hreq , arg ,
sizeof ( compat_xfs_fsop_attrmulti_handlereq_t ) ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2008-11-26 06:20:15 +03:00
2010-03-23 01:51:22 +03:00
/* overflow check */
if ( am_hreq . opcount > = INT_MAX / sizeof ( compat_xfs_attr_multiop_t ) )
return - E2BIG ;
2009-01-19 04:02:57 +03:00
dentry = xfs_compat_handlereq_to_dentry ( parfilp , & am_hreq . hreq ) ;
if ( IS_ERR ( dentry ) )
return PTR_ERR ( dentry ) ;
2008-11-26 06:20:15 +03:00
2014-06-25 08:58:08 +04:00
error = - E2BIG ;
2008-11-26 06:20:15 +03:00
size = am_hreq . opcount * sizeof ( compat_xfs_attr_multiop_t ) ;
if ( ! size | | size > 16 * PAGE_SIZE )
2009-01-19 04:02:57 +03:00
goto out_dput ;
2008-11-26 06:20:15 +03:00
2009-04-08 11:08:04 +04:00
ops = memdup_user ( compat_ptr ( am_hreq . ops ) , size ) ;
if ( IS_ERR ( ops ) ) {
2015-01-22 02:04:24 +03:00
error = PTR_ERR ( ops ) ;
2009-01-19 04:02:57 +03:00
goto out_dput ;
2009-04-08 11:08:04 +04:00
}
2008-11-26 06:20:15 +03:00
error = 0 ;
for ( i = 0 ; i < am_hreq . opcount ; i + + ) {
2020-02-27 04:30:31 +03:00
ops [ i ] . am_error = xfs_ioc_attrmulti_one ( parfilp ,
d_inode ( dentry ) , ops [ i ] . am_opcode ,
compat_ptr ( ops [ i ] . am_attrname ) ,
compat_ptr ( ops [ i ] . am_attrvalue ) ,
& ops [ i ] . am_length , ops [ i ] . am_flags ) ;
2008-11-26 06:20:15 +03:00
}
if ( copy_to_user ( compat_ptr ( am_hreq . ops ) , ops , size ) )
2014-06-25 08:58:08 +04:00
error = - EFAULT ;
2008-11-26 06:20:15 +03:00
kfree ( ops ) ;
2009-01-19 04:02:57 +03:00
out_dput :
dput ( dentry ) ;
2014-06-25 08:58:08 +04:00
return error ;
2008-11-26 06:20:15 +03:00
}
2008-12-09 12:47:33 +03:00
long
xfs_file_compat_ioctl (
struct file * filp ,
unsigned cmd ,
unsigned long p )
2005-04-17 02:20:36 +04:00
{
2013-01-24 02:07:38 +04:00
struct inode * inode = file_inode ( filp ) ;
2008-12-09 12:47:33 +03:00
struct xfs_inode * ip = XFS_I ( inode ) ;
struct xfs_mount * mp = ip - > i_mount ;
2019-08-16 09:41:06 +03:00
void __user * arg = compat_ptr ( p ) ;
2008-12-09 12:47:33 +03:00
int error ;
2010-06-24 05:57:09 +04:00
trace_xfs_file_compat_ioctl ( ip ) ;
2005-04-17 02:20:36 +04:00
switch ( cmd ) {
2018-12-17 20:35:27 +03:00
# if defined(BROKEN_X86_ALIGNMENT)
2005-09-05 02:25:06 +04:00
case XFS_IOC_ALLOCSP_32 :
case XFS_IOC_FREESP_32 :
case XFS_IOC_ALLOCSP64_32 :
2019-10-25 08:26:02 +03:00
case XFS_IOC_FREESP64_32 : {
2008-11-26 06:20:08 +03:00
struct xfs_flock64 bf ;
if ( xfs_compat_flock64_copyin ( & bf , arg ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2005-09-05 02:25:06 +04:00
cmd = _NATIVE_IOC ( cmd , struct xfs_flock64 ) ;
2019-10-25 08:26:02 +03:00
return xfs_ioc_space ( filp , & bf ) ;
2008-11-26 06:20:08 +03:00
}
2007-07-11 05:09:57 +04:00
case XFS_IOC_FSGEOMETRY_V1_32 :
2008-11-26 06:20:08 +03:00
return xfs_compat_ioc_fsgeometry_v1 ( mp , arg ) ;
2008-11-26 06:20:10 +03:00
case XFS_IOC_FSGROWFSDATA_32 : {
struct xfs_growfs_data in ;
if ( xfs_compat_growfs_data_copyin ( & in , arg ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2012-06-12 18:20:39 +04:00
error = mnt_want_write_file ( filp ) ;
if ( error )
return error ;
2008-11-26 06:20:10 +03:00
error = xfs_growfs_data ( mp , & in ) ;
2012-06-12 18:20:39 +04:00
mnt_drop_write_file ( filp ) ;
2014-06-25 08:58:08 +04:00
return error ;
2008-11-26 06:20:10 +03:00
}
case XFS_IOC_FSGROWFSRT_32 : {
struct xfs_growfs_rt in ;
if ( xfs_compat_growfs_rt_copyin ( & in , arg ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2012-06-12 18:20:39 +04:00
error = mnt_want_write_file ( filp ) ;
if ( error )
return error ;
2008-11-26 06:20:10 +03:00
error = xfs_growfs_rt ( mp , & in ) ;
2012-06-12 18:20:39 +04:00
mnt_drop_write_file ( filp ) ;
2014-06-25 08:58:08 +04:00
return error ;
2008-11-26 06:20:10 +03:00
}
2005-04-17 02:20:36 +04:00
# endif
2008-11-26 06:20:17 +03:00
/* long changes size, but xfs only copiese out 32 bits */
case XFS_IOC_GETXFLAGS_32 :
case XFS_IOC_SETXFLAGS_32 :
case XFS_IOC_GETVERSION_32 :
cmd = _NATIVE_IOC ( cmd , long ) ;
2008-12-09 12:47:33 +03:00
return xfs_file_ioctl ( filp , cmd , p ) ;
2009-09-01 22:03:08 +04:00
case XFS_IOC_SWAPEXT_32 : {
2008-11-26 06:20:17 +03:00
struct xfs_swapext sxp ;
struct compat_xfs_swapext __user * sxu = arg ;
/* Bulk copy in up to the sx_stat field, then copy bstat */
if ( copy_from_user ( & sxp , sxu ,
offsetof ( struct xfs_swapext , sx_stat ) ) | |
xfs_ioctl32_bstat_copyin ( & sxp . sx_stat , & sxu - > sx_stat ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2012-06-12 18:20:39 +04:00
error = mnt_want_write_file ( filp ) ;
if ( error )
return error ;
2013-08-12 14:49:48 +04:00
error = xfs_ioc_swapext ( & sxp ) ;
2012-06-12 18:20:39 +04:00
mnt_drop_write_file ( filp ) ;
2014-06-25 08:58:08 +04:00
return error ;
2008-11-26 06:20:17 +03:00
}
2007-07-11 05:10:19 +04:00
case XFS_IOC_FSBULKSTAT_32 :
case XFS_IOC_FSBULKSTAT_SINGLE_32 :
case XFS_IOC_FSINUMBERS_32 :
2019-07-04 06:36:26 +03:00
return xfs_compat_ioc_fsbulkstat ( mp , cmd , arg ) ;
2007-07-11 05:10:09 +04:00
case XFS_IOC_FD_TO_HANDLE_32 :
case XFS_IOC_PATH_TO_HANDLE_32 :
2008-11-26 06:20:08 +03:00
case XFS_IOC_PATH_TO_FSHANDLE_32 : {
struct xfs_fsop_handlereq hreq ;
if ( xfs_compat_handlereq_copyin ( & hreq , arg ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2007-07-11 05:10:09 +04:00
cmd = _NATIVE_IOC ( cmd , struct xfs_fsop_handlereq ) ;
2008-11-26 06:20:08 +03:00
return xfs_find_handle ( cmd , & hreq ) ;
}
case XFS_IOC_OPEN_BY_HANDLE_32 : {
struct xfs_fsop_handlereq hreq ;
if ( xfs_compat_handlereq_copyin ( & hreq , arg ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2009-01-19 04:02:57 +03:00
return xfs_open_by_handle ( filp , & hreq ) ;
2008-11-26 06:20:08 +03:00
}
case XFS_IOC_READLINK_BY_HANDLE_32 : {
struct xfs_fsop_handlereq hreq ;
if ( xfs_compat_handlereq_copyin ( & hreq , arg ) )
2014-06-22 09:04:54 +04:00
return - EFAULT ;
2009-01-19 04:02:57 +03:00
return xfs_readlink_by_handle ( filp , & hreq ) ;
2008-11-26 06:20:08 +03:00
}
2008-11-26 06:20:14 +03:00
case XFS_IOC_ATTRLIST_BY_HANDLE_32 :
2009-01-19 04:02:57 +03:00
return xfs_compat_attrlist_by_handle ( filp , arg ) ;
2008-11-26 06:20:15 +03:00
case XFS_IOC_ATTRMULTI_BY_HANDLE_32 :
2009-01-19 04:02:57 +03:00
return xfs_compat_attrmulti_by_handle ( filp , arg ) ;
2005-04-17 02:20:36 +04:00
default :
2019-08-16 09:41:06 +03:00
/* try the native version */
2019-08-16 09:41:06 +03:00
return xfs_file_ioctl ( filp , cmd , ( unsigned long ) arg ) ;
2005-04-17 02:20:36 +04:00
}
}