1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2004-2005 Silicon Graphics, Inc. 4 * All Rights Reserved. 5 */ 6 #include <linux/mount.h> 7 #include <linux/fsmap.h> 8 #include "xfs.h" 9 #include "xfs_fs.h" 10 #include "xfs_shared.h" 11 #include "xfs_format.h" 12 #include "xfs_log_format.h" 13 #include "xfs_trans_resv.h" 14 #include "xfs_mount.h" 15 #include "xfs_inode.h" 16 #include "xfs_iwalk.h" 17 #include "xfs_itable.h" 18 #include "xfs_fsops.h" 19 #include "xfs_rtalloc.h" 20 #include "xfs_attr.h" 21 #include "xfs_ioctl.h" 22 #include "xfs_ioctl32.h" 23 #include "xfs_trace.h" 24 #include "xfs_sb.h" 25 26 #define _NATIVE_IOC(cmd, type) \ 27 _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) 28 29 #ifdef BROKEN_X86_ALIGNMENT 30 STATIC int 31 xfs_compat_ioc_fsgeometry_v1( 32 struct xfs_mount *mp, 33 compat_xfs_fsop_geom_v1_t __user *arg32) 34 { 35 struct xfs_fsop_geom fsgeo; 36 37 xfs_fs_geometry(mp, &fsgeo, 3); 38 /* The 32-bit variant simply has some padding at the end */ 39 if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1))) 40 return -EFAULT; 41 return 0; 42 } 43 44 STATIC int 45 xfs_compat_growfs_data_copyin( 46 struct xfs_growfs_data *in, 47 compat_xfs_growfs_data_t __user *arg32) 48 { 49 if (get_user(in->newblocks, &arg32->newblocks) || 50 get_user(in->imaxpct, &arg32->imaxpct)) 51 return -EFAULT; 52 return 0; 53 } 54 55 STATIC int 56 xfs_compat_growfs_rt_copyin( 57 struct xfs_growfs_rt *in, 58 compat_xfs_growfs_rt_t __user *arg32) 59 { 60 if (get_user(in->newblocks, &arg32->newblocks) || 61 get_user(in->extsize, &arg32->extsize)) 62 return -EFAULT; 63 return 0; 64 } 65 66 STATIC int 67 xfs_fsinumbers_fmt_compat( 68 struct xfs_ibulk *breq, 69 const struct xfs_inumbers *ig) 70 { 71 struct compat_xfs_inogrp __user *p32 = breq->ubuffer; 72 struct xfs_inogrp ig1; 73 struct xfs_inogrp *igrp = &ig1; 74 75 xfs_inumbers_to_inogrp(&ig1, ig); 76 77 if (put_user(igrp->xi_startino, &p32->xi_startino) || 78 put_user(igrp->xi_alloccount, &p32->xi_alloccount) || 79 put_user(igrp->xi_allocmask, &p32->xi_allocmask)) 80 return -EFAULT; 81 82 return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_inogrp)); 83 } 84 85 #else 86 #define xfs_fsinumbers_fmt_compat xfs_fsinumbers_fmt 87 #endif /* BROKEN_X86_ALIGNMENT */ 88 89 STATIC int 90 xfs_ioctl32_bstime_copyin( 91 xfs_bstime_t *bstime, 92 compat_xfs_bstime_t __user *bstime32) 93 { 94 old_time32_t sec32; /* tv_sec differs on 64 vs. 32 */ 95 96 if (get_user(sec32, &bstime32->tv_sec) || 97 get_user(bstime->tv_nsec, &bstime32->tv_nsec)) 98 return -EFAULT; 99 bstime->tv_sec = sec32; 100 return 0; 101 } 102 103 /* 104 * struct xfs_bstat has differing alignment on intel, & bstime_t sizes 105 * everywhere 106 */ 107 STATIC int 108 xfs_ioctl32_bstat_copyin( 109 struct xfs_bstat *bstat, 110 struct compat_xfs_bstat __user *bstat32) 111 { 112 if (get_user(bstat->bs_ino, &bstat32->bs_ino) || 113 get_user(bstat->bs_mode, &bstat32->bs_mode) || 114 get_user(bstat->bs_nlink, &bstat32->bs_nlink) || 115 get_user(bstat->bs_uid, &bstat32->bs_uid) || 116 get_user(bstat->bs_gid, &bstat32->bs_gid) || 117 get_user(bstat->bs_rdev, &bstat32->bs_rdev) || 118 get_user(bstat->bs_blksize, &bstat32->bs_blksize) || 119 get_user(bstat->bs_size, &bstat32->bs_size) || 120 xfs_ioctl32_bstime_copyin(&bstat->bs_atime, &bstat32->bs_atime) || 121 xfs_ioctl32_bstime_copyin(&bstat->bs_mtime, &bstat32->bs_mtime) || 122 xfs_ioctl32_bstime_copyin(&bstat->bs_ctime, &bstat32->bs_ctime) || 123 get_user(bstat->bs_blocks, &bstat32->bs_size) || 124 get_user(bstat->bs_xflags, &bstat32->bs_size) || 125 get_user(bstat->bs_extsize, &bstat32->bs_extsize) || 126 get_user(bstat->bs_extents, &bstat32->bs_extents) || 127 get_user(bstat->bs_gen, &bstat32->bs_gen) || 128 get_user(bstat->bs_projid_lo, &bstat32->bs_projid_lo) || 129 get_user(bstat->bs_projid_hi, &bstat32->bs_projid_hi) || 130 get_user(bstat->bs_forkoff, &bstat32->bs_forkoff) || 131 get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask) || 132 get_user(bstat->bs_dmstate, &bstat32->bs_dmstate) || 133 get_user(bstat->bs_aextents, &bstat32->bs_aextents)) 134 return -EFAULT; 135 return 0; 136 } 137 138 /* XFS_IOC_FSBULKSTAT and friends */ 139 140 STATIC int 141 xfs_bstime_store_compat( 142 compat_xfs_bstime_t __user *p32, 143 const xfs_bstime_t *p) 144 { 145 __s32 sec32; 146 147 sec32 = p->tv_sec; 148 if (put_user(sec32, &p32->tv_sec) || 149 put_user(p->tv_nsec, &p32->tv_nsec)) 150 return -EFAULT; 151 return 0; 152 } 153 154 /* Return 0 on success or positive error (to xfs_bulkstat()) */ 155 STATIC int 156 xfs_fsbulkstat_one_fmt_compat( 157 struct xfs_ibulk *breq, 158 const struct xfs_bulkstat *bstat) 159 { 160 struct compat_xfs_bstat __user *p32 = breq->ubuffer; 161 struct xfs_bstat bs1; 162 struct xfs_bstat *buffer = &bs1; 163 164 xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat); 165 166 if (put_user(buffer->bs_ino, &p32->bs_ino) || 167 put_user(buffer->bs_mode, &p32->bs_mode) || 168 put_user(buffer->bs_nlink, &p32->bs_nlink) || 169 put_user(buffer->bs_uid, &p32->bs_uid) || 170 put_user(buffer->bs_gid, &p32->bs_gid) || 171 put_user(buffer->bs_rdev, &p32->bs_rdev) || 172 put_user(buffer->bs_blksize, &p32->bs_blksize) || 173 put_user(buffer->bs_size, &p32->bs_size) || 174 xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || 175 xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || 176 xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || 177 put_user(buffer->bs_blocks, &p32->bs_blocks) || 178 put_user(buffer->bs_xflags, &p32->bs_xflags) || 179 put_user(buffer->bs_extsize, &p32->bs_extsize) || 180 put_user(buffer->bs_extents, &p32->bs_extents) || 181 put_user(buffer->bs_gen, &p32->bs_gen) || 182 put_user(buffer->bs_projid, &p32->bs_projid) || 183 put_user(buffer->bs_projid_hi, &p32->bs_projid_hi) || 184 put_user(buffer->bs_forkoff, &p32->bs_forkoff) || 185 put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || 186 put_user(buffer->bs_dmstate, &p32->bs_dmstate) || 187 put_user(buffer->bs_aextents, &p32->bs_aextents)) 188 return -EFAULT; 189 190 return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_bstat)); 191 } 192 193 /* copied from xfs_ioctl.c */ 194 STATIC int 195 xfs_compat_ioc_fsbulkstat( 196 struct file *file, 197 unsigned int cmd, 198 struct compat_xfs_fsop_bulkreq __user *p32) 199 { 200 struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount; 201 u32 addr; 202 struct xfs_fsop_bulkreq bulkreq; 203 struct xfs_ibulk breq = { 204 .mp = mp, 205 .mnt_userns = file_mnt_user_ns(file), 206 .ocount = 0, 207 }; 208 xfs_ino_t lastino; 209 int error; 210 211 /* 212 * Output structure handling functions. Depending on the command, 213 * either the xfs_bstat and xfs_inogrp structures are written out 214 * to userpace memory via bulkreq.ubuffer. Normally the compat 215 * functions and structure size are the correct ones to use ... 216 */ 217 inumbers_fmt_pf inumbers_func = xfs_fsinumbers_fmt_compat; 218 bulkstat_one_fmt_pf bs_one_func = xfs_fsbulkstat_one_fmt_compat; 219 220 #ifdef CONFIG_X86_X32 221 if (in_x32_syscall()) { 222 /* 223 * ... but on x32 the input xfs_fsop_bulkreq has pointers 224 * which must be handled in the "compat" (32-bit) way, while 225 * the xfs_bstat and xfs_inogrp structures follow native 64- 226 * bit layout convention. So adjust accordingly, otherwise 227 * the data written out in compat layout will not match what 228 * x32 userspace expects. 229 */ 230 inumbers_func = xfs_fsinumbers_fmt; 231 bs_one_func = xfs_fsbulkstat_one_fmt; 232 } 233 #endif 234 235 /* done = 1 if there are more stats to get and if bulkstat */ 236 /* should be called again (unused here, but used in dmapi) */ 237 238 if (!capable(CAP_SYS_ADMIN)) 239 return -EPERM; 240 241 if (xfs_is_shutdown(mp)) 242 return -EIO; 243 244 if (get_user(addr, &p32->lastip)) 245 return -EFAULT; 246 bulkreq.lastip = compat_ptr(addr); 247 if (get_user(bulkreq.icount, &p32->icount) || 248 get_user(addr, &p32->ubuffer)) 249 return -EFAULT; 250 bulkreq.ubuffer = compat_ptr(addr); 251 if (get_user(addr, &p32->ocount)) 252 return -EFAULT; 253 bulkreq.ocount = compat_ptr(addr); 254 255 if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64))) 256 return -EFAULT; 257 258 if (bulkreq.icount <= 0) 259 return -EINVAL; 260 261 if (bulkreq.ubuffer == NULL) 262 return -EINVAL; 263 264 breq.ubuffer = bulkreq.ubuffer; 265 breq.icount = bulkreq.icount; 266 267 /* 268 * FSBULKSTAT_SINGLE expects that *lastip contains the inode number 269 * that we want to stat. However, FSINUMBERS and FSBULKSTAT expect 270 * that *lastip contains either zero or the number of the last inode to 271 * be examined by the previous call and return results starting with 272 * the next inode after that. The new bulk request back end functions 273 * take the inode to start with, so we have to compute the startino 274 * parameter from lastino to maintain correct function. lastino == 0 275 * is a special case because it has traditionally meant "first inode 276 * in filesystem". 277 */ 278 if (cmd == XFS_IOC_FSINUMBERS_32) { 279 breq.startino = lastino ? lastino + 1 : 0; 280 error = xfs_inumbers(&breq, inumbers_func); 281 lastino = breq.startino - 1; 282 } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { 283 breq.startino = lastino; 284 breq.icount = 1; 285 error = xfs_bulkstat_one(&breq, bs_one_func); 286 lastino = breq.startino; 287 } else if (cmd == XFS_IOC_FSBULKSTAT_32) { 288 breq.startino = lastino ? lastino + 1 : 0; 289 error = xfs_bulkstat(&breq, bs_one_func); 290 lastino = breq.startino - 1; 291 } else { 292 error = -EINVAL; 293 } 294 if (error) 295 return error; 296 297 if (bulkreq.lastip != NULL && 298 copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t))) 299 return -EFAULT; 300 301 if (bulkreq.ocount != NULL && 302 copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32))) 303 return -EFAULT; 304 305 return 0; 306 } 307 308 STATIC int 309 xfs_compat_handlereq_copyin( 310 xfs_fsop_handlereq_t *hreq, 311 compat_xfs_fsop_handlereq_t __user *arg32) 312 { 313 compat_xfs_fsop_handlereq_t hreq32; 314 315 if (copy_from_user(&hreq32, arg32, sizeof(compat_xfs_fsop_handlereq_t))) 316 return -EFAULT; 317 318 hreq->fd = hreq32.fd; 319 hreq->path = compat_ptr(hreq32.path); 320 hreq->oflags = hreq32.oflags; 321 hreq->ihandle = compat_ptr(hreq32.ihandle); 322 hreq->ihandlen = hreq32.ihandlen; 323 hreq->ohandle = compat_ptr(hreq32.ohandle); 324 hreq->ohandlen = compat_ptr(hreq32.ohandlen); 325 326 return 0; 327 } 328 329 STATIC struct dentry * 330 xfs_compat_handlereq_to_dentry( 331 struct file *parfilp, 332 compat_xfs_fsop_handlereq_t *hreq) 333 { 334 return xfs_handle_to_dentry(parfilp, 335 compat_ptr(hreq->ihandle), hreq->ihandlen); 336 } 337 338 STATIC int 339 xfs_compat_attrlist_by_handle( 340 struct file *parfilp, 341 compat_xfs_fsop_attrlist_handlereq_t __user *p) 342 { 343 compat_xfs_fsop_attrlist_handlereq_t al_hreq; 344 struct dentry *dentry; 345 int error; 346 347 if (!capable(CAP_SYS_ADMIN)) 348 return -EPERM; 349 if (copy_from_user(&al_hreq, p, sizeof(al_hreq))) 350 return -EFAULT; 351 352 dentry = xfs_compat_handlereq_to_dentry(parfilp, &al_hreq.hreq); 353 if (IS_ERR(dentry)) 354 return PTR_ERR(dentry); 355 356 error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), 357 compat_ptr(al_hreq.buffer), al_hreq.buflen, 358 al_hreq.flags, &p->pos); 359 dput(dentry); 360 return error; 361 } 362 363 STATIC int 364 xfs_compat_attrmulti_by_handle( 365 struct file *parfilp, 366 void __user *arg) 367 { 368 int error; 369 compat_xfs_attr_multiop_t *ops; 370 compat_xfs_fsop_attrmulti_handlereq_t am_hreq; 371 struct dentry *dentry; 372 unsigned int i, size; 373 374 if (!capable(CAP_SYS_ADMIN)) 375 return -EPERM; 376 if (copy_from_user(&am_hreq, arg, 377 sizeof(compat_xfs_fsop_attrmulti_handlereq_t))) 378 return -EFAULT; 379 380 /* overflow check */ 381 if (am_hreq.opcount >= INT_MAX / sizeof(compat_xfs_attr_multiop_t)) 382 return -E2BIG; 383 384 dentry = xfs_compat_handlereq_to_dentry(parfilp, &am_hreq.hreq); 385 if (IS_ERR(dentry)) 386 return PTR_ERR(dentry); 387 388 error = -E2BIG; 389 size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); 390 if (!size || size > 16 * PAGE_SIZE) 391 goto out_dput; 392 393 ops = memdup_user(compat_ptr(am_hreq.ops), size); 394 if (IS_ERR(ops)) { 395 error = PTR_ERR(ops); 396 goto out_dput; 397 } 398 399 error = 0; 400 for (i = 0; i < am_hreq.opcount; i++) { 401 ops[i].am_error = xfs_ioc_attrmulti_one(parfilp, 402 d_inode(dentry), ops[i].am_opcode, 403 compat_ptr(ops[i].am_attrname), 404 compat_ptr(ops[i].am_attrvalue), 405 &ops[i].am_length, ops[i].am_flags); 406 } 407 408 if (copy_to_user(compat_ptr(am_hreq.ops), ops, size)) 409 error = -EFAULT; 410 411 kfree(ops); 412 out_dput: 413 dput(dentry); 414 return error; 415 } 416 417 long 418 xfs_file_compat_ioctl( 419 struct file *filp, 420 unsigned cmd, 421 unsigned long p) 422 { 423 struct inode *inode = file_inode(filp); 424 struct xfs_inode *ip = XFS_I(inode); 425 void __user *arg = compat_ptr(p); 426 int error; 427 428 trace_xfs_file_compat_ioctl(ip); 429 430 switch (cmd) { 431 #if defined(BROKEN_X86_ALIGNMENT) 432 case XFS_IOC_FSGEOMETRY_V1_32: 433 return xfs_compat_ioc_fsgeometry_v1(ip->i_mount, arg); 434 case XFS_IOC_FSGROWFSDATA_32: { 435 struct xfs_growfs_data in; 436 437 if (xfs_compat_growfs_data_copyin(&in, arg)) 438 return -EFAULT; 439 error = mnt_want_write_file(filp); 440 if (error) 441 return error; 442 error = xfs_growfs_data(ip->i_mount, &in); 443 mnt_drop_write_file(filp); 444 return error; 445 } 446 case XFS_IOC_FSGROWFSRT_32: { 447 struct xfs_growfs_rt in; 448 449 if (xfs_compat_growfs_rt_copyin(&in, arg)) 450 return -EFAULT; 451 error = mnt_want_write_file(filp); 452 if (error) 453 return error; 454 error = xfs_growfs_rt(ip->i_mount, &in); 455 mnt_drop_write_file(filp); 456 return error; 457 } 458 #endif 459 /* long changes size, but xfs only copiese out 32 bits */ 460 case XFS_IOC_GETVERSION_32: 461 cmd = _NATIVE_IOC(cmd, long); 462 return xfs_file_ioctl(filp, cmd, p); 463 case XFS_IOC_SWAPEXT_32: { 464 struct xfs_swapext sxp; 465 struct compat_xfs_swapext __user *sxu = arg; 466 467 /* Bulk copy in up to the sx_stat field, then copy bstat */ 468 if (copy_from_user(&sxp, sxu, 469 offsetof(struct xfs_swapext, sx_stat)) || 470 xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) 471 return -EFAULT; 472 error = mnt_want_write_file(filp); 473 if (error) 474 return error; 475 error = xfs_ioc_swapext(&sxp); 476 mnt_drop_write_file(filp); 477 return error; 478 } 479 case XFS_IOC_FSBULKSTAT_32: 480 case XFS_IOC_FSBULKSTAT_SINGLE_32: 481 case XFS_IOC_FSINUMBERS_32: 482 return xfs_compat_ioc_fsbulkstat(filp, cmd, arg); 483 case XFS_IOC_FD_TO_HANDLE_32: 484 case XFS_IOC_PATH_TO_HANDLE_32: 485 case XFS_IOC_PATH_TO_FSHANDLE_32: { 486 struct xfs_fsop_handlereq hreq; 487 488 if (xfs_compat_handlereq_copyin(&hreq, arg)) 489 return -EFAULT; 490 cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); 491 return xfs_find_handle(cmd, &hreq); 492 } 493 case XFS_IOC_OPEN_BY_HANDLE_32: { 494 struct xfs_fsop_handlereq hreq; 495 496 if (xfs_compat_handlereq_copyin(&hreq, arg)) 497 return -EFAULT; 498 return xfs_open_by_handle(filp, &hreq); 499 } 500 case XFS_IOC_READLINK_BY_HANDLE_32: { 501 struct xfs_fsop_handlereq hreq; 502 503 if (xfs_compat_handlereq_copyin(&hreq, arg)) 504 return -EFAULT; 505 return xfs_readlink_by_handle(filp, &hreq); 506 } 507 case XFS_IOC_ATTRLIST_BY_HANDLE_32: 508 return xfs_compat_attrlist_by_handle(filp, arg); 509 case XFS_IOC_ATTRMULTI_BY_HANDLE_32: 510 return xfs_compat_attrmulti_by_handle(filp, arg); 511 default: 512 /* try the native version */ 513 return xfs_file_ioctl(filp, cmd, (unsigned long)arg); 514 } 515 } 516