Blame view
fs/xfs/xfs_ioctl32.c
18 KB
1da177e4c
|
1 |
/* |
7b7187698
|
2 3 |
* Copyright (c) 2004-2005 Silicon Graphics, Inc. * All Rights Reserved. |
1da177e4c
|
4 |
* |
7b7187698
|
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
|
7 8 |
* published by the Free Software Foundation. * |
7b7187698
|
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
|
13 |
* |
7b7187698
|
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
|
17 |
*/ |
1da177e4c
|
18 |
#include <linux/compat.h> |
1da177e4c
|
19 |
#include <linux/ioctl.h> |
62e194ecd
|
20 |
#include <linux/mount.h> |
5a0e3ad6a
|
21 |
#include <linux/slab.h> |
1da177e4c
|
22 |
#include <asm/uaccess.h> |
1da177e4c
|
23 |
#include "xfs.h" |
1da177e4c
|
24 |
#include "xfs_fs.h" |
faa63e958
|
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
|
31 32 |
#include "xfs_mount.h" #include "xfs_bmap_btree.h" |
1da177e4c
|
33 |
#include "xfs_vnode.h" |
faa63e958
|
34 35 36 37 |
#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_itable.h" #include "xfs_error.h" |
1da177e4c
|
38 |
#include "xfs_dfrag.h" |
739bfb2a7
|
39 |
#include "xfs_vnodeops.h" |
d5547f9fe
|
40 |
#include "xfs_fsops.h" |
471d59103
|
41 42 |
#include "xfs_alloc.h" #include "xfs_rtalloc.h" |
ebeecd2b0
|
43 |
#include "xfs_attr.h" |
d5547f9fe
|
44 |
#include "xfs_ioctl.h" |
a8272ce0c
|
45 |
#include "xfs_ioctl32.h" |
0b1b213fc
|
46 |
#include "xfs_trace.h" |
1da177e4c
|
47 |
|
526c420c4
|
48 49 |
#define _NATIVE_IOC(cmd, type) \ _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) |
ffae263a6
|
50 |
#ifdef BROKEN_X86_ALIGNMENT |
d5547f9fe
|
51 52 53 54 |
STATIC int xfs_compat_flock64_copyin( xfs_flock64_t *bf, compat_xfs_flock64_t __user *arg32) |
526c420c4
|
55 |
{ |
d5547f9fe
|
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
|
65 |
} |
d5547f9fe
|
66 67 68 69 |
STATIC int xfs_compat_ioc_fsgeometry_v1( struct xfs_mount *mp, compat_xfs_fsop_geom_v1_t __user *arg32) |
547e00c3c
|
70 |
{ |
d5547f9fe
|
71 72 |
xfs_fsop_geom_t fsgeo; int error; |
547e00c3c
|
73 |
|
d5547f9fe
|
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
|
81 |
} |
d5547f9fe
|
82 |
STATIC int |
471d59103
|
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
|
105 106 107 108 109 |
xfs_inumbers_fmt_compat( void __user *ubuffer, const xfs_inogrp_t *buffer, long count, long *written) |
faa63e958
|
110 |
{ |
d5547f9fe
|
111 112 |
compat_xfs_inogrp_t __user *p32 = ubuffer; long i; |
faa63e958
|
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
|
118 |
return -XFS_ERROR(EFAULT); |
faa63e958
|
119 120 121 122 |
} *written = count * sizeof(*p32); return 0; } |
1da177e4c
|
123 |
#else |
faa63e958
|
124 |
#define xfs_inumbers_fmt_compat xfs_inumbers_fmt |
e5d412f17
|
125 |
#endif /* BROKEN_X86_ALIGNMENT */ |
faa63e958
|
126 |
|
e94fc4a43
|
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
|
163 164 |
get_user(bstat->bs_projid_lo, &bstat32->bs_projid_lo) || get_user(bstat->bs_projid_hi, &bstat32->bs_projid_hi) || |
e94fc4a43
|
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
|
171 |
/* XFS_IOC_FSBULKSTAT and friends */ |
d5547f9fe
|
172 173 174 175 |
STATIC int xfs_bstime_store_compat( compat_xfs_bstime_t __user *p32, const xfs_bstime_t *p) |
faa63e958
|
176 |
{ |
d5547f9fe
|
177 |
__s32 sec32; |
faa63e958
|
178 179 180 181 |
sec32 = p->tv_sec; if (put_user(sec32, &p32->tv_sec) || put_user(p->tv_nsec, &p32->tv_nsec)) |
d5547f9fe
|
182 |
return -XFS_ERROR(EFAULT); |
faa63e958
|
183 184 |
return 0; } |
65fbaf248
|
185 |
/* Return 0 on success or positive error (to xfs_bulkstat()) */ |
d5547f9fe
|
186 187 |
STATIC int xfs_bulkstat_one_fmt_compat( |
faa63e958
|
188 |
void __user *ubuffer, |
65fbaf248
|
189 190 |
int ubsize, int *ubused, |
faa63e958
|
191 192 |
const xfs_bstat_t *buffer) { |
d5547f9fe
|
193 |
compat_xfs_bstat_t __user *p32 = ubuffer; |
faa63e958
|
194 |
|
65fbaf248
|
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
|
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
|
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
|
215 |
put_user(buffer->bs_projid_hi, &p32->bs_projid_hi) || |
65fbaf248
|
216 217 |
put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || put_user(buffer->bs_dmstate, &p32->bs_dmstate) || |
faa63e958
|
218 |
put_user(buffer->bs_aextents, &p32->bs_aextents)) |
65fbaf248
|
219 220 221 222 |
return XFS_ERROR(EFAULT); if (ubused) *ubused = sizeof(*p32); return 0; |
faa63e958
|
223 |
} |
2ee4fa5cb
|
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
|
230 |
int *ubused, /* bytes used by me */ |
2ee4fa5cb
|
231 232 233 |
int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, |
7b6259e7a
|
234 |
xfs_bulkstat_one_fmt_compat, |
7dce11dba
|
235 |
ubused, stat); |
2ee4fa5cb
|
236 |
} |
faa63e958
|
237 238 |
/* copied from xfs_ioctl.c */ STATIC int |
2ee4fa5cb
|
239 240 241 242 |
xfs_compat_ioc_bulkstat( xfs_mount_t *mp, unsigned int cmd, compat_xfs_fsop_bulkreq_t __user *p32) |
1da177e4c
|
243 |
{ |
1da177e4c
|
244 |
u32 addr; |
faa63e958
|
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
|
253 |
|
faa63e958
|
254 |
if (!capable(CAP_SYS_ADMIN)) |
d5547f9fe
|
255 |
return -XFS_ERROR(EPERM); |
faa63e958
|
256 257 258 259 260 |
if (XFS_FORCED_SHUTDOWN(mp)) return -XFS_ERROR(EIO); if (get_user(addr, &p32->lastip)) |
d5547f9fe
|
261 |
return -XFS_ERROR(EFAULT); |
faa63e958
|
262 263 264 |
bulkreq.lastip = compat_ptr(addr); if (get_user(bulkreq.icount, &p32->icount) || get_user(addr, &p32->ubuffer)) |
d5547f9fe
|
265 |
return -XFS_ERROR(EFAULT); |
faa63e958
|
266 267 |
bulkreq.ubuffer = compat_ptr(addr); if (get_user(addr, &p32->ocount)) |
d5547f9fe
|
268 |
return -XFS_ERROR(EFAULT); |
faa63e958
|
269 |
bulkreq.ocount = compat_ptr(addr); |
1da177e4c
|
270 |
|
faa63e958
|
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
|
276 277 |
if (bulkreq.ubuffer == NULL) return -XFS_ERROR(EINVAL); |
af819d276
|
278 |
if (cmd == XFS_IOC_FSINUMBERS_32) { |
faa63e958
|
279 280 |
error = xfs_inumbers(mp, &inlast, &count, bulkreq.ubuffer, xfs_inumbers_fmt_compat); |
af819d276
|
281 282 283 284 |
} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { int res; error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer, |
7b6259e7a
|
285 |
sizeof(compat_xfs_bstat_t), 0, &res); |
af819d276
|
286 |
} else if (cmd == XFS_IOC_FSBULKSTAT_32) { |
faa63e958
|
287 |
error = xfs_bulkstat(mp, &inlast, &count, |
7dce11dba
|
288 289 |
xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, &done); |
af819d276
|
290 291 |
} else error = XFS_ERROR(EINVAL); |
faa63e958
|
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
|
305 |
} |
faa63e958
|
306 |
|
d5547f9fe
|
307 308 309 310 |
STATIC int xfs_compat_handlereq_copyin( xfs_fsop_handlereq_t *hreq, compat_xfs_fsop_handlereq_t __user *arg32) |
1fa503df6
|
311 |
{ |
d5547f9fe
|
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
|
326 |
} |
ab596ad89
|
327 328 329 330 |
STATIC struct dentry * xfs_compat_handlereq_to_dentry( struct file *parfilp, compat_xfs_fsop_handlereq_t *hreq) |
ebeecd2b0
|
331 |
{ |
ab596ad89
|
332 333 |
return xfs_handle_to_dentry(parfilp, compat_ptr(hreq->ihandle), hreq->ihandlen); |
ebeecd2b0
|
334 335 336 337 |
} STATIC int xfs_compat_attrlist_by_handle( |
ab596ad89
|
338 339 |
struct file *parfilp, void __user *arg) |
ebeecd2b0
|
340 341 342 343 |
{ int error; attrlist_cursor_kern_t *cursor; compat_xfs_fsop_attrlist_handlereq_t al_hreq; |
ab596ad89
|
344 |
struct dentry *dentry; |
ebeecd2b0
|
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
|
360 361 362 |
dentry = xfs_compat_handlereq_to_dentry(parfilp, &al_hreq.hreq); if (IS_ERR(dentry)) return PTR_ERR(dentry); |
ebeecd2b0
|
363 |
|
ab596ad89
|
364 |
error = -ENOMEM; |
ebeecd2b0
|
365 366 |
kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); if (!kbuf) |
ab596ad89
|
367 |
goto out_dput; |
ebeecd2b0
|
368 369 |
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; |
ab596ad89
|
370 |
error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, |
ebeecd2b0
|
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
|
380 381 382 |
out_dput: dput(dentry); return error; |
ebeecd2b0
|
383 |
} |
28750975a
|
384 385 |
STATIC int xfs_compat_attrmulti_by_handle( |
ab596ad89
|
386 387 |
struct file *parfilp, void __user *arg) |
28750975a
|
388 389 390 391 |
{ int error; compat_xfs_attr_multiop_t *ops; compat_xfs_fsop_attrmulti_handlereq_t am_hreq; |
ab596ad89
|
392 |
struct dentry *dentry; |
28750975a
|
393 |
unsigned int i, size; |
a9273ca5c
|
394 |
unsigned char *attr_name; |
28750975a
|
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
|
401 402 403 |
/* overflow check */ if (am_hreq.opcount >= INT_MAX / sizeof(compat_xfs_attr_multiop_t)) return -E2BIG; |
ab596ad89
|
404 405 406 |
dentry = xfs_compat_handlereq_to_dentry(parfilp, &am_hreq.hreq); if (IS_ERR(dentry)) return PTR_ERR(dentry); |
28750975a
|
407 408 409 410 |
error = E2BIG; size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); if (!size || size > 16 * PAGE_SIZE) |
ab596ad89
|
411 |
goto out_dput; |
28750975a
|
412 |
|
0e639bdee
|
413 414 415 |
ops = memdup_user(compat_ptr(am_hreq.ops), size); if (IS_ERR(ops)) { error = PTR_ERR(ops); |
ab596ad89
|
416 |
goto out_dput; |
0e639bdee
|
417 |
} |
28750975a
|
418 419 420 421 |
attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); if (!attr_name) goto out_kfree_ops; |
28750975a
|
422 423 |
error = 0; for (i = 0; i < am_hreq.opcount; i++) { |
a9273ca5c
|
424 |
ops[i].am_error = strncpy_from_user((char *)attr_name, |
28750975a
|
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
|
434 435 |
ops[i].am_error = xfs_attrmulti_attr_get( dentry->d_inode, attr_name, |
28750975a
|
436 437 438 439 |
compat_ptr(ops[i].am_attrvalue), &ops[i].am_length, ops[i].am_flags); break; case ATTR_OP_SET: |
a561be710
|
440 |
ops[i].am_error = mnt_want_write_file(parfilp); |
62e194ecd
|
441 442 |
if (ops[i].am_error) break; |
ab596ad89
|
443 444 |
ops[i].am_error = xfs_attrmulti_attr_set( dentry->d_inode, attr_name, |
28750975a
|
445 446 |
compat_ptr(ops[i].am_attrvalue), ops[i].am_length, ops[i].am_flags); |
2a79f17e4
|
447 |
mnt_drop_write_file(parfilp); |
28750975a
|
448 449 |
break; case ATTR_OP_REMOVE: |
a561be710
|
450 |
ops[i].am_error = mnt_want_write_file(parfilp); |
62e194ecd
|
451 452 |
if (ops[i].am_error) break; |
ab596ad89
|
453 454 455 |
ops[i].am_error = xfs_attrmulti_attr_remove( dentry->d_inode, attr_name, ops[i].am_flags); |
2a79f17e4
|
456 |
mnt_drop_write_file(parfilp); |
28750975a
|
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
|
469 470 |
out_dput: dput(dentry); |
28750975a
|
471 472 |
return -error; } |
710d62aaa
|
473 474 |
STATIC int xfs_compat_fssetdm_by_handle( |
ab596ad89
|
475 476 |
struct file *parfilp, void __user *arg) |
710d62aaa
|
477 478 479 480 |
{ int error; struct fsdmidata fsd; compat_xfs_fsop_setdm_handlereq_t dmhreq; |
ab596ad89
|
481 |
struct dentry *dentry; |
710d62aaa
|
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
|
488 489 490 |
dentry = xfs_compat_handlereq_to_dentry(parfilp, &dmhreq.hreq); if (IS_ERR(dentry)) return PTR_ERR(dentry); |
710d62aaa
|
491 |
|
ab596ad89
|
492 |
if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { |
710d62aaa
|
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
|
501 |
error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask, |
710d62aaa
|
502 503 504 |
fsd.fsd_dmstate); out: |
ab596ad89
|
505 |
dput(dentry); |
710d62aaa
|
506 507 |
return error; } |
4d4be482a
|
508 509 510 511 512 |
long xfs_file_compat_ioctl( struct file *filp, unsigned cmd, unsigned long p) |
1da177e4c
|
513 |
{ |
4d4be482a
|
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
|
523 |
trace_xfs_file_compat_ioctl(ip); |
1da177e4c
|
524 525 |
switch (cmd) { |
e5d412f17
|
526 |
/* No size or alignment issues on any arch */ |
1da177e4c
|
527 |
case XFS_IOC_DIOINFO: |
1da177e4c
|
528 |
case XFS_IOC_FSGEOMETRY: |
1da177e4c
|
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
|
536 537 538 |
case XFS_IOC_FSCOUNTS: case XFS_IOC_SET_RESBLKS: case XFS_IOC_GET_RESBLKS: |
1da177e4c
|
539 |
case XFS_IOC_FSGROWFSLOG: |
1da177e4c
|
540 541 542 |
case XFS_IOC_GOINGDOWN: case XFS_IOC_ERROR_INJECTION: case XFS_IOC_ERROR_CLEARALL: |
4d4be482a
|
543 |
return xfs_file_ioctl(filp, cmd, p); |
e5d412f17
|
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
|
557 |
case XFS_IOC_ZERO_RANGE: |
4d4be482a
|
558 |
return xfs_file_ioctl(filp, cmd, p); |
e5d412f17
|
559 |
#else |
526c420c4
|
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
|
567 568 |
case XFS_IOC_UNRESVSP64_32: case XFS_IOC_ZERO_RANGE_32: { |
d5547f9fe
|
569 570 571 572 |
struct xfs_flock64 bf; if (xfs_compat_flock64_copyin(&bf, arg)) return -XFS_ERROR(EFAULT); |
526c420c4
|
573 |
cmd = _NATIVE_IOC(cmd, struct xfs_flock64); |
d5547f9fe
|
574 575 |
return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); } |
547e00c3c
|
576 |
case XFS_IOC_FSGEOMETRY_V1_32: |
d5547f9fe
|
577 |
return xfs_compat_ioc_fsgeometry_v1(mp, arg); |
471d59103
|
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
|
594 |
#endif |
e5d412f17
|
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
|
600 |
return xfs_file_ioctl(filp, cmd, p); |
3725867dc
|
601 |
case XFS_IOC_SWAPEXT_32: { |
e5d412f17
|
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
|
613 614 615 |
case XFS_IOC_FSBULKSTAT_32: case XFS_IOC_FSBULKSTAT_SINGLE_32: case XFS_IOC_FSINUMBERS_32: |
2ee4fa5cb
|
616 |
return xfs_compat_ioc_bulkstat(mp, cmd, arg); |
1fa503df6
|
617 618 |
case XFS_IOC_FD_TO_HANDLE_32: case XFS_IOC_PATH_TO_HANDLE_32: |
d5547f9fe
|
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
|
624 |
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); |
d5547f9fe
|
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
|
632 |
return xfs_open_by_handle(filp, &hreq); |
d5547f9fe
|
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
|
639 |
return xfs_readlink_by_handle(filp, &hreq); |
d5547f9fe
|
640 |
} |
ebeecd2b0
|
641 |
case XFS_IOC_ATTRLIST_BY_HANDLE_32: |
ab596ad89
|
642 |
return xfs_compat_attrlist_by_handle(filp, arg); |
28750975a
|
643 |
case XFS_IOC_ATTRMULTI_BY_HANDLE_32: |
ab596ad89
|
644 |
return xfs_compat_attrmulti_by_handle(filp, arg); |
710d62aaa
|
645 |
case XFS_IOC_FSSETDM_BY_HANDLE_32: |
ab596ad89
|
646 |
return xfs_compat_fssetdm_by_handle(filp, arg); |
1da177e4c
|
647 |
default: |
d5547f9fe
|
648 |
return -XFS_ERROR(ENOIOCTLCMD); |
1da177e4c
|
649 |
} |
1da177e4c
|
650 |
} |