Blame view

fs/xfs/xfs_ioctl32.c 18 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
7b7187698   Nathan Scott   [XFS] Update lice...
2
3
   * Copyright (c) 2004-2005 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
7b7187698   Nathan Scott   [XFS] Update lice...
5
6
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   * published by the Free Software Foundation.
   *
7b7187698   Nathan Scott   [XFS] Update lice...
9
10
11
12
   * This program is distributed in the hope that it would be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   *
7b7187698   Nathan Scott   [XFS] Update lice...
14
15
16
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write the Free Software Foundation,
   * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/ioctl.h>
62e194ecd   Christoph Hellwig   xfs: use mnt_want...
20
  #include <linux/mount.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #include "xfs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
  #include "xfs_fs.h"
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
25
26
27
28
29
30
  #include "xfs_bit.h"
  #include "xfs_log.h"
  #include "xfs_inum.h"
  #include "xfs_trans.h"
  #include "xfs_sb.h"
  #include "xfs_ag.h"
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
31
32
  #include "xfs_mount.h"
  #include "xfs_bmap_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include "xfs_vnode.h"
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
34
35
36
37
  #include "xfs_dinode.h"
  #include "xfs_inode.h"
  #include "xfs_itable.h"
  #include "xfs_error.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  #include "xfs_dfrag.h"
739bfb2a7   Christoph Hellwig   [XFS] call common...
39
  #include "xfs_vnodeops.h"
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
40
  #include "xfs_fsops.h"
471d59103   sandeen@sandeen.net   [XFS] Add compat ...
41
42
  #include "xfs_alloc.h"
  #include "xfs_rtalloc.h"
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
43
  #include "xfs_attr.h"
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
44
  #include "xfs_ioctl.h"
a8272ce0c   David Chinner   [XFS] Fix up spar...
45
  #include "xfs_ioctl32.h"
0b1b213fc   Christoph Hellwig   xfs: event tracin...
46
  #include "xfs_trace.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

526c420c4   Eric Sandeen   [XFS] add handler...
48
49
  #define  _NATIVE_IOC(cmd, type) \
  	  _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
ffae263a6   sandeen@sandeen.net   [XFS] Move compat...
50
  #ifdef BROKEN_X86_ALIGNMENT
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
51
52
53
54
  STATIC int
  xfs_compat_flock64_copyin(
  	xfs_flock64_t		*bf,
  	compat_xfs_flock64_t	__user *arg32)
526c420c4   Eric Sandeen   [XFS] add handler...
55
  {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
56
57
58
59
60
61
62
63
64
  	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)))
  		return -XFS_ERROR(EFAULT);
  	return 0;
526c420c4   Eric Sandeen   [XFS] add handler...
65
  }
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
66
67
68
69
  STATIC int
  xfs_compat_ioc_fsgeometry_v1(
  	struct xfs_mount	  *mp,
  	compat_xfs_fsop_geom_v1_t __user *arg32)
547e00c3c   Michal Marek   [XFS] Compat ioct...
70
  {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
71
72
  	xfs_fsop_geom_t		  fsgeo;
  	int			  error;
547e00c3c   Michal Marek   [XFS] Compat ioct...
73

d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
74
75
76
77
78
79
80
  	error = xfs_fs_geometry(mp, &fsgeo, 3);
  	if (error)
  		return -error;
  	/* The 32-bit variant simply has some padding at the end */
  	if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1)))
  		return -XFS_ERROR(EFAULT);
  	return 0;
547e00c3c   Michal Marek   [XFS] Compat ioct...
81
  }
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
82
  STATIC int
471d59103   sandeen@sandeen.net   [XFS] Add compat ...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  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))
  		return -XFS_ERROR(EFAULT);
  	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))
  		return -XFS_ERROR(EFAULT);
  	return 0;
  }
  
  STATIC int
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
105
106
107
108
109
  xfs_inumbers_fmt_compat(
  	void			__user *ubuffer,
  	const xfs_inogrp_t	*buffer,
  	long			count,
  	long			*written)
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
110
  {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
111
112
  	compat_xfs_inogrp_t	__user *p32 = ubuffer;
  	long			i;
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
113
114
115
116
117
  
  	for (i = 0; i < count; i++) {
  		if (put_user(buffer[i].xi_startino,   &p32[i].xi_startino) ||
  		    put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
  		    put_user(buffer[i].xi_allocmask,  &p32[i].xi_allocmask))
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
118
  			return -XFS_ERROR(EFAULT);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
119
120
121
122
  	}
  	*written = count * sizeof(*p32);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  #else
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
124
  #define xfs_inumbers_fmt_compat xfs_inumbers_fmt
e5d412f17   sandeen@sandeen.net   [XFS] Reorder xfs...
125
  #endif	/* BROKEN_X86_ALIGNMENT */
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
126

e94fc4a43   sandeen@sandeen.net   [XFS] Add compat ...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  STATIC int
  xfs_ioctl32_bstime_copyin(
  	xfs_bstime_t		*bstime,
  	compat_xfs_bstime_t	__user *bstime32)
  {
  	compat_time_t		sec32;	/* tv_sec differs on 64 vs. 32 */
  
  	if (get_user(sec32,		&bstime32->tv_sec)	||
  	    get_user(bstime->tv_nsec,	&bstime32->tv_nsec))
  		return -XFS_ERROR(EFAULT);
  	bstime->tv_sec = sec32;
  	return 0;
  }
  
  /* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */
  STATIC int
  xfs_ioctl32_bstat_copyin(
  	xfs_bstat_t		*bstat,
  	compat_xfs_bstat_t	__user *bstat32)
  {
  	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)	||
6743099ce   Arkadiusz Mi?kiewicz   xfs: Extend proje...
163
164
  	    get_user(bstat->bs_projid_lo, &bstat32->bs_projid_lo) ||
  	    get_user(bstat->bs_projid_hi, &bstat32->bs_projid_hi) ||
e94fc4a43   sandeen@sandeen.net   [XFS] Add compat ...
165
166
167
168
169
170
  	    get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask)	||
  	    get_user(bstat->bs_dmstate,	&bstat32->bs_dmstate)	||
  	    get_user(bstat->bs_aextents, &bstat32->bs_aextents))
  		return -XFS_ERROR(EFAULT);
  	return 0;
  }
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
171
  /* XFS_IOC_FSBULKSTAT and friends */
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
172
173
174
175
  STATIC int
  xfs_bstime_store_compat(
  	compat_xfs_bstime_t	__user *p32,
  	const xfs_bstime_t	*p)
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
176
  {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
177
  	__s32			sec32;
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
178
179
180
181
  
  	sec32 = p->tv_sec;
  	if (put_user(sec32, &p32->tv_sec) ||
  	    put_user(p->tv_nsec, &p32->tv_nsec))
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
182
  		return -XFS_ERROR(EFAULT);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
183
184
  	return 0;
  }
65fbaf248   sandeen@sandeen.net   [XFS] Fix xfs_bul...
185
  /* Return 0 on success or positive error (to xfs_bulkstat()) */
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
186
187
  STATIC int
  xfs_bulkstat_one_fmt_compat(
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
188
  	void			__user *ubuffer,
65fbaf248   sandeen@sandeen.net   [XFS] Fix xfs_bul...
189
190
  	int			ubsize,
  	int			*ubused,
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
191
192
  	const xfs_bstat_t	*buffer)
  {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
193
  	compat_xfs_bstat_t	__user *p32 = ubuffer;
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
194

65fbaf248   sandeen@sandeen.net   [XFS] Fix xfs_bul...
195
196
197
198
199
200
201
202
203
204
205
  	if (ubsize < sizeof(*p32))
  		return XFS_ERROR(ENOMEM);
  
  	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)	||
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
206
207
208
  	    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) ||
65fbaf248   sandeen@sandeen.net   [XFS] Fix xfs_bul...
209
210
211
212
213
214
  	    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)	||
6743099ce   Arkadiusz Mi?kiewicz   xfs: Extend proje...
215
  	    put_user(buffer->bs_projid_hi,	&p32->bs_projid_hi)	||
65fbaf248   sandeen@sandeen.net   [XFS] Fix xfs_bul...
216
217
  	    put_user(buffer->bs_dmevmask, &p32->bs_dmevmask)	||
  	    put_user(buffer->bs_dmstate,  &p32->bs_dmstate)	||
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
218
  	    put_user(buffer->bs_aextents, &p32->bs_aextents))
65fbaf248   sandeen@sandeen.net   [XFS] Fix xfs_bul...
219
220
221
222
  		return XFS_ERROR(EFAULT);
  	if (ubused)
  		*ubused = sizeof(*p32);
  	return 0;
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
223
  }
2ee4fa5cb   sandeen@sandeen.net   [XFS] Make the bu...
224
225
226
227
228
229
  STATIC int
  xfs_bulkstat_one_compat(
  	xfs_mount_t	*mp,		/* mount point for filesystem */
  	xfs_ino_t	ino,		/* inode number to get data for */
  	void		__user *buffer,	/* buffer to place output in */
  	int		ubsize,		/* size of buffer */
2ee4fa5cb   sandeen@sandeen.net   [XFS] Make the bu...
230
  	int		*ubused,	/* bytes used by me */
2ee4fa5cb   sandeen@sandeen.net   [XFS] Make the bu...
231
232
233
  	int		*stat)		/* BULKSTAT_RV_... */
  {
  	return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
7b6259e7a   Dave Chinner   xfs: remove block...
234
  				    xfs_bulkstat_one_fmt_compat,
7dce11dba   Christoph Hellwig   xfs: always use i...
235
  				    ubused, stat);
2ee4fa5cb   sandeen@sandeen.net   [XFS] Make the bu...
236
  }
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
237
238
  /* copied from xfs_ioctl.c */
  STATIC int
2ee4fa5cb   sandeen@sandeen.net   [XFS] Make the bu...
239
240
241
242
  xfs_compat_ioc_bulkstat(
  	xfs_mount_t		  *mp,
  	unsigned int		  cmd,
  	compat_xfs_fsop_bulkreq_t __user *p32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  	u32			addr;
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
245
246
247
248
249
250
251
252
  	xfs_fsop_bulkreq_t	bulkreq;
  	int			count;	/* # of records returned */
  	xfs_ino_t		inlast;	/* last inode number */
  	int			done;
  	int			error;
  
  	/* done = 1 if there are more stats to get and if bulkstat */
  	/* should be called again (unused here, but used in dmapi) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
254
  	if (!capable(CAP_SYS_ADMIN))
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
255
  		return -XFS_ERROR(EPERM);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
256
257
258
259
260
  
  	if (XFS_FORCED_SHUTDOWN(mp))
  		return -XFS_ERROR(EIO);
  
  	if (get_user(addr, &p32->lastip))
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
261
  		return -XFS_ERROR(EFAULT);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
262
263
264
  	bulkreq.lastip = compat_ptr(addr);
  	if (get_user(bulkreq.icount, &p32->icount) ||
  	    get_user(addr, &p32->ubuffer))
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
265
  		return -XFS_ERROR(EFAULT);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
266
267
  	bulkreq.ubuffer = compat_ptr(addr);
  	if (get_user(addr, &p32->ocount))
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
268
  		return -XFS_ERROR(EFAULT);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
269
  	bulkreq.ocount = compat_ptr(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270

faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
271
272
273
274
275
  	if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
  		return -XFS_ERROR(EFAULT);
  
  	if ((count = bulkreq.icount) <= 0)
  		return -XFS_ERROR(EINVAL);
cd57e594a   Lachlan McIlroy   [XFS] 971064 Vari...
276
277
  	if (bulkreq.ubuffer == NULL)
  		return -XFS_ERROR(EINVAL);
af819d276   sandeen@sandeen.net   [XFS] Fix compat ...
278
  	if (cmd == XFS_IOC_FSINUMBERS_32) {
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
279
280
  		error = xfs_inumbers(mp, &inlast, &count,
  				bulkreq.ubuffer, xfs_inumbers_fmt_compat);
af819d276   sandeen@sandeen.net   [XFS] Fix compat ...
281
282
283
284
  	} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
  		int res;
  
  		error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
7b6259e7a   Dave Chinner   xfs: remove block...
285
  				sizeof(compat_xfs_bstat_t), 0, &res);
af819d276   sandeen@sandeen.net   [XFS] Fix compat ...
286
  	} else if (cmd == XFS_IOC_FSBULKSTAT_32) {
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
287
  		error = xfs_bulkstat(mp, &inlast, &count,
7dce11dba   Christoph Hellwig   xfs: always use i...
288
289
  			xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
  			bulkreq.ubuffer, &done);
af819d276   sandeen@sandeen.net   [XFS] Fix compat ...
290
291
  	} else
  		error = XFS_ERROR(EINVAL);
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
292
293
294
295
296
297
298
299
300
301
302
303
304
  	if (error)
  		return -error;
  
  	if (bulkreq.ocount != NULL) {
  		if (copy_to_user(bulkreq.lastip, &inlast,
  						sizeof(xfs_ino_t)))
  			return -XFS_ERROR(EFAULT);
  
  		if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
  			return -XFS_ERROR(EFAULT);
  	}
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  }
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
306

d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
307
308
309
310
  STATIC int
  xfs_compat_handlereq_copyin(
  	xfs_fsop_handlereq_t		*hreq,
  	compat_xfs_fsop_handlereq_t	__user *arg32)
1fa503df6   Michal Marek   [XFS] Compat ioct...
311
  {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  	compat_xfs_fsop_handlereq_t	hreq32;
  
  	if (copy_from_user(&hreq32, arg32, sizeof(compat_xfs_fsop_handlereq_t)))
  		return -XFS_ERROR(EFAULT);
  
  	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;
1fa503df6   Michal Marek   [XFS] Compat ioct...
326
  }
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
327
328
329
330
  STATIC struct dentry *
  xfs_compat_handlereq_to_dentry(
  	struct file		*parfilp,
  	compat_xfs_fsop_handlereq_t *hreq)
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
331
  {
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
332
333
  	return xfs_handle_to_dentry(parfilp,
  			compat_ptr(hreq->ihandle), hreq->ihandlen);
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
334
335
336
337
  }
  
  STATIC int
  xfs_compat_attrlist_by_handle(
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
338
339
  	struct file		*parfilp,
  	void			__user *arg)
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
340
341
342
343
  {
  	int			error;
  	attrlist_cursor_kern_t	*cursor;
  	compat_xfs_fsop_attrlist_handlereq_t al_hreq;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
344
  	struct dentry		*dentry;
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  	char			*kbuf;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -XFS_ERROR(EPERM);
  	if (copy_from_user(&al_hreq, arg,
  			   sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
  		return -XFS_ERROR(EFAULT);
  	if (al_hreq.buflen > XATTR_LIST_MAX)
  		return -XFS_ERROR(EINVAL);
  
  	/*
  	 * Reject flags, only allow namespaces.
  	 */
  	if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
  		return -XFS_ERROR(EINVAL);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
360
361
362
  	dentry = xfs_compat_handlereq_to_dentry(parfilp, &al_hreq.hreq);
  	if (IS_ERR(dentry))
  		return PTR_ERR(dentry);
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
363

ab596ad89   Christoph Hellwig   xfs: fix dentry a...
364
  	error = -ENOMEM;
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
365
366
  	kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL);
  	if (!kbuf)
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
367
  		goto out_dput;
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
368
369
  
  	cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
370
  	error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
371
372
373
374
375
376
377
378
379
  					al_hreq.flags, cursor);
  	if (error)
  		goto out_kfree;
  
  	if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
  		error = -EFAULT;
  
   out_kfree:
  	kfree(kbuf);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
380
381
382
   out_dput:
  	dput(dentry);
  	return error;
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
383
  }
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
384
385
  STATIC int
  xfs_compat_attrmulti_by_handle(
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
386
387
  	struct file				*parfilp,
  	void					__user *arg)
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
388
389
390
391
  {
  	int					error;
  	compat_xfs_attr_multiop_t		*ops;
  	compat_xfs_fsop_attrmulti_handlereq_t	am_hreq;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
392
  	struct dentry				*dentry;
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
393
  	unsigned int				i, size;
a9273ca5c   Dave Chinner   xfs: convert attr...
394
  	unsigned char				*attr_name;
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
395
396
397
398
399
400
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -XFS_ERROR(EPERM);
  	if (copy_from_user(&am_hreq, arg,
  			   sizeof(compat_xfs_fsop_attrmulti_handlereq_t)))
  		return -XFS_ERROR(EFAULT);
fda168c24   Zhitong Wang   xfs: Fix integer ...
401
402
403
  	/* overflow check */
  	if (am_hreq.opcount >= INT_MAX / sizeof(compat_xfs_attr_multiop_t))
  		return -E2BIG;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
404
405
406
  	dentry = xfs_compat_handlereq_to_dentry(parfilp, &am_hreq.hreq);
  	if (IS_ERR(dentry))
  		return PTR_ERR(dentry);
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
407
408
409
410
  
  	error = E2BIG;
  	size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t);
  	if (!size || size > 16 * PAGE_SIZE)
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
411
  		goto out_dput;
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
412

0e639bdee   Li Zefan   xfs: use memdup_u...
413
414
415
  	ops = memdup_user(compat_ptr(am_hreq.ops), size);
  	if (IS_ERR(ops)) {
  		error = PTR_ERR(ops);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
416
  		goto out_dput;
0e639bdee   Li Zefan   xfs: use memdup_u...
417
  	}
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
418
419
420
421
  
  	attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
  	if (!attr_name)
  		goto out_kfree_ops;
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
422
423
  	error = 0;
  	for (i = 0; i < am_hreq.opcount; i++) {
a9273ca5c   Dave Chinner   xfs: convert attr...
424
  		ops[i].am_error = strncpy_from_user((char *)attr_name,
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
425
426
427
428
429
430
431
432
433
  				compat_ptr(ops[i].am_attrname),
  				MAXNAMELEN);
  		if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
  			error = -ERANGE;
  		if (ops[i].am_error < 0)
  			break;
  
  		switch (ops[i].am_opcode) {
  		case ATTR_OP_GET:
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
434
435
  			ops[i].am_error = xfs_attrmulti_attr_get(
  					dentry->d_inode, attr_name,
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
436
437
438
439
  					compat_ptr(ops[i].am_attrvalue),
  					&ops[i].am_length, ops[i].am_flags);
  			break;
  		case ATTR_OP_SET:
a561be710   Al Viro   switch a bunch of...
440
  			ops[i].am_error = mnt_want_write_file(parfilp);
62e194ecd   Christoph Hellwig   xfs: use mnt_want...
441
442
  			if (ops[i].am_error)
  				break;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
443
444
  			ops[i].am_error = xfs_attrmulti_attr_set(
  					dentry->d_inode, attr_name,
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
445
446
  					compat_ptr(ops[i].am_attrvalue),
  					ops[i].am_length, ops[i].am_flags);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
447
  			mnt_drop_write_file(parfilp);
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
448
449
  			break;
  		case ATTR_OP_REMOVE:
a561be710   Al Viro   switch a bunch of...
450
  			ops[i].am_error = mnt_want_write_file(parfilp);
62e194ecd   Christoph Hellwig   xfs: use mnt_want...
451
452
  			if (ops[i].am_error)
  				break;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
453
454
455
  			ops[i].am_error = xfs_attrmulti_attr_remove(
  					dentry->d_inode, attr_name,
  					ops[i].am_flags);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
456
  			mnt_drop_write_file(parfilp);
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
457
458
459
460
461
462
463
464
465
466
467
468
  			break;
  		default:
  			ops[i].am_error = EINVAL;
  		}
  	}
  
  	if (copy_to_user(compat_ptr(am_hreq.ops), ops, size))
  		error = XFS_ERROR(EFAULT);
  
  	kfree(attr_name);
   out_kfree_ops:
  	kfree(ops);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
469
470
   out_dput:
  	dput(dentry);
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
471
472
  	return -error;
  }
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
473
474
  STATIC int
  xfs_compat_fssetdm_by_handle(
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
475
476
  	struct file		*parfilp,
  	void			__user *arg)
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
477
478
479
480
  {
  	int			error;
  	struct fsdmidata	fsd;
  	compat_xfs_fsop_setdm_handlereq_t dmhreq;
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
481
  	struct dentry		*dentry;
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
482
483
484
485
486
487
  
  	if (!capable(CAP_MKNOD))
  		return -XFS_ERROR(EPERM);
  	if (copy_from_user(&dmhreq, arg,
  			   sizeof(compat_xfs_fsop_setdm_handlereq_t)))
  		return -XFS_ERROR(EFAULT);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
488
489
490
  	dentry = xfs_compat_handlereq_to_dentry(parfilp, &dmhreq.hreq);
  	if (IS_ERR(dentry))
  		return PTR_ERR(dentry);
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
491

ab596ad89   Christoph Hellwig   xfs: fix dentry a...
492
  	if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
493
494
495
496
497
498
499
500
  		error = -XFS_ERROR(EPERM);
  		goto out;
  	}
  
  	if (copy_from_user(&fsd, compat_ptr(dmhreq.data), sizeof(fsd))) {
  		error = -XFS_ERROR(EFAULT);
  		goto out;
  	}
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
501
  	error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask,
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
502
503
504
  				 fsd.fsd_dmstate);
  
  out:
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
505
  	dput(dentry);
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
506
507
  	return error;
  }
4d4be482a   Christoph Hellwig   [XFS] add a FMODE...
508
509
510
511
512
  long
  xfs_file_compat_ioctl(
  	struct file		*filp,
  	unsigned		cmd,
  	unsigned long		p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  {
4d4be482a   Christoph Hellwig   [XFS] add a FMODE...
514
515
516
517
518
519
520
521
522
  	struct inode		*inode = filp->f_path.dentry->d_inode;
  	struct xfs_inode	*ip = XFS_I(inode);
  	struct xfs_mount	*mp = ip->i_mount;
  	void			__user *arg = (void __user *)p;
  	int			ioflags = 0;
  	int			error;
  
  	if (filp->f_mode & FMODE_NOCMTIME)
  		ioflags |= IO_INVIS;
cca28fb83   Christoph Hellwig   xfs: split xfs_it...
523
  	trace_xfs_file_compat_ioctl(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
  
  	switch (cmd) {
e5d412f17   sandeen@sandeen.net   [XFS] Reorder xfs...
526
  	/* No size or alignment issues on any arch */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  	case XFS_IOC_DIOINFO:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
  	case XFS_IOC_FSGEOMETRY:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
534
535
  	case XFS_IOC_FSGETXATTR:
  	case XFS_IOC_FSSETXATTR:
  	case XFS_IOC_FSGETXATTRA:
  	case XFS_IOC_FSSETDM:
  	case XFS_IOC_GETBMAP:
  	case XFS_IOC_GETBMAPA:
  	case XFS_IOC_GETBMAPX:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
  	case XFS_IOC_FSCOUNTS:
  	case XFS_IOC_SET_RESBLKS:
  	case XFS_IOC_GET_RESBLKS:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
  	case XFS_IOC_FSGROWFSLOG:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
  	case XFS_IOC_GOINGDOWN:
  	case XFS_IOC_ERROR_INJECTION:
  	case XFS_IOC_ERROR_CLEARALL:
4d4be482a   Christoph Hellwig   [XFS] add a FMODE...
543
  		return xfs_file_ioctl(filp, cmd, p);
e5d412f17   sandeen@sandeen.net   [XFS] Reorder xfs...
544
545
546
547
548
549
550
551
552
553
554
555
556
  #ifndef BROKEN_X86_ALIGNMENT
  	/* These are handled fine if no alignment issues */
  	case XFS_IOC_ALLOCSP:
  	case XFS_IOC_FREESP:
  	case XFS_IOC_RESVSP:
  	case XFS_IOC_UNRESVSP:
  	case XFS_IOC_ALLOCSP64:
  	case XFS_IOC_FREESP64:
  	case XFS_IOC_RESVSP64:
  	case XFS_IOC_UNRESVSP64:
  	case XFS_IOC_FSGEOMETRY_V1:
  	case XFS_IOC_FSGROWFSDATA:
  	case XFS_IOC_FSGROWFSRT:
447223520   Dave Chinner   xfs: Introduce XF...
557
  	case XFS_IOC_ZERO_RANGE:
4d4be482a   Christoph Hellwig   [XFS] add a FMODE...
558
  		return xfs_file_ioctl(filp, cmd, p);
e5d412f17   sandeen@sandeen.net   [XFS] Reorder xfs...
559
  #else
526c420c4   Eric Sandeen   [XFS] add handler...
560
561
562
563
564
565
566
  	case XFS_IOC_ALLOCSP_32:
  	case XFS_IOC_FREESP_32:
  	case XFS_IOC_ALLOCSP64_32:
  	case XFS_IOC_FREESP64_32:
  	case XFS_IOC_RESVSP_32:
  	case XFS_IOC_UNRESVSP_32:
  	case XFS_IOC_RESVSP64_32:
8c1fdd0be   Christoph Hellwig   xfs: add an x86 c...
567
568
  	case XFS_IOC_UNRESVSP64_32:
  	case XFS_IOC_ZERO_RANGE_32: {
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
569
570
571
572
  		struct xfs_flock64	bf;
  
  		if (xfs_compat_flock64_copyin(&bf, arg))
  			return -XFS_ERROR(EFAULT);
526c420c4   Eric Sandeen   [XFS] add handler...
573
  		cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
574
575
  		return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
  	}
547e00c3c   Michal Marek   [XFS] Compat ioct...
576
  	case XFS_IOC_FSGEOMETRY_V1_32:
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
577
  		return xfs_compat_ioc_fsgeometry_v1(mp, arg);
471d59103   sandeen@sandeen.net   [XFS] Add compat ...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  	case XFS_IOC_FSGROWFSDATA_32: {
  		struct xfs_growfs_data	in;
  
  		if (xfs_compat_growfs_data_copyin(&in, arg))
  			return -XFS_ERROR(EFAULT);
  		error = xfs_growfs_data(mp, &in);
  		return -error;
  	}
  	case XFS_IOC_FSGROWFSRT_32: {
  		struct xfs_growfs_rt	in;
  
  		if (xfs_compat_growfs_rt_copyin(&in, arg))
  			return -XFS_ERROR(EFAULT);
  		error = xfs_growfs_rt(mp, &in);
  		return -error;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  #endif
e5d412f17   sandeen@sandeen.net   [XFS] Reorder xfs...
595
596
597
598
599
  	/* 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);
4d4be482a   Christoph Hellwig   [XFS] add a FMODE...
600
  		return xfs_file_ioctl(filp, cmd, p);
3725867dc   Christoph Hellwig   xfs: actually ena...
601
  	case XFS_IOC_SWAPEXT_32: {
e5d412f17   sandeen@sandeen.net   [XFS] Reorder xfs...
602
603
604
605
606
607
608
609
610
611
612
  		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))
  			return -XFS_ERROR(EFAULT);
  		error = xfs_swapext(&sxp);
  		return -error;
  	}
faa63e958   Michal Marek   [XFS] Fix XFS_IOC...
613
614
615
  	case XFS_IOC_FSBULKSTAT_32:
  	case XFS_IOC_FSBULKSTAT_SINGLE_32:
  	case XFS_IOC_FSINUMBERS_32:
2ee4fa5cb   sandeen@sandeen.net   [XFS] Make the bu...
616
  		return xfs_compat_ioc_bulkstat(mp, cmd, arg);
1fa503df6   Michal Marek   [XFS] Compat ioct...
617
618
  	case XFS_IOC_FD_TO_HANDLE_32:
  	case XFS_IOC_PATH_TO_HANDLE_32:
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
619
620
621
622
623
  	case XFS_IOC_PATH_TO_FSHANDLE_32: {
  		struct xfs_fsop_handlereq	hreq;
  
  		if (xfs_compat_handlereq_copyin(&hreq, arg))
  			return -XFS_ERROR(EFAULT);
1fa503df6   Michal Marek   [XFS] Compat ioct...
624
  		cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
625
626
627
628
629
630
631
  		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))
  			return -XFS_ERROR(EFAULT);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
632
  		return xfs_open_by_handle(filp, &hreq);
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
633
634
635
636
637
638
  	}
  	case XFS_IOC_READLINK_BY_HANDLE_32: {
  		struct xfs_fsop_handlereq	hreq;
  
  		if (xfs_compat_handlereq_copyin(&hreq, arg))
  			return -XFS_ERROR(EFAULT);
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
639
  		return xfs_readlink_by_handle(filp, &hreq);
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
640
  	}
ebeecd2b0   sandeen@sandeen.net   [XFS] Hook up com...
641
  	case XFS_IOC_ATTRLIST_BY_HANDLE_32:
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
642
  		return xfs_compat_attrlist_by_handle(filp, arg);
28750975a   sandeen@sandeen.net   [XFS] Hook up com...
643
  	case XFS_IOC_ATTRMULTI_BY_HANDLE_32:
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
644
  		return xfs_compat_attrmulti_by_handle(filp, arg);
710d62aaa   sandeen@sandeen.net   [XFS] Hook up com...
645
  	case XFS_IOC_FSSETDM_BY_HANDLE_32:
ab596ad89   Christoph Hellwig   xfs: fix dentry a...
646
  		return xfs_compat_fssetdm_by_handle(filp, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  	default:
d5547f9fe   sandeen@sandeen.net   [XFS] Clean up so...
648
  		return -XFS_ERROR(ENOIOCTLCMD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  }