1400 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.4 * All Rights Reserved.5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "xfs_log_format.h"11#include "xfs_trans_resv.h"12#include "xfs_mount.h"13#include "xfs_inode.h"14#include "xfs_rtalloc.h"15#include "xfs_iwalk.h"16#include "xfs_itable.h"17#include "xfs_error.h"18#include "xfs_da_format.h"19#include "xfs_da_btree.h"20#include "xfs_attr.h"21#include "xfs_bmap.h"22#include "xfs_bmap_util.h"23#include "xfs_fsops.h"24#include "xfs_discard.h"25#include "xfs_quota.h"26#include "xfs_trace.h"27#include "xfs_icache.h"28#include "xfs_trans.h"29#include "xfs_btree.h"30#include <linux/fsmap.h>31#include "xfs_fsmap.h"32#include "scrub/xfs_scrub.h"33#include "xfs_sb.h"34#include "xfs_ag.h"35#include "xfs_health.h"36#include "xfs_reflink.h"37#include "xfs_ioctl.h"38#include "xfs_xattr.h"39#include "xfs_rtbitmap.h"40#include "xfs_file.h"41#include "xfs_exchrange.h"42#include "xfs_handle.h"43 44#include <linux/mount.h>45#include <linux/fileattr.h>46 47/* Return 0 on success or positive error */48int49xfs_fsbulkstat_one_fmt(50 struct xfs_ibulk *breq,51 const struct xfs_bulkstat *bstat)52{53 struct xfs_bstat bs1;54 55 xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);56 if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))57 return -EFAULT;58 return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));59}60 61int62xfs_fsinumbers_fmt(63 struct xfs_ibulk *breq,64 const struct xfs_inumbers *igrp)65{66 struct xfs_inogrp ig1;67 68 xfs_inumbers_to_inogrp(&ig1, igrp);69 if (copy_to_user(breq->ubuffer, &ig1, sizeof(struct xfs_inogrp)))70 return -EFAULT;71 return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));72}73 74STATIC int75xfs_ioc_fsbulkstat(76 struct file *file,77 unsigned int cmd,78 void __user *arg)79{80 struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount;81 struct xfs_fsop_bulkreq bulkreq;82 struct xfs_ibulk breq = {83 .mp = mp,84 .idmap = file_mnt_idmap(file),85 .ocount = 0,86 };87 xfs_ino_t lastino;88 int error;89 90 /* done = 1 if there are more stats to get and if bulkstat */91 /* should be called again (unused here, but used in dmapi) */92 93 if (!capable(CAP_SYS_ADMIN))94 return -EPERM;95 96 if (xfs_is_shutdown(mp))97 return -EIO;98 99 if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))100 return -EFAULT;101 102 if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))103 return -EFAULT;104 105 if (bulkreq.icount <= 0)106 return -EINVAL;107 108 if (bulkreq.ubuffer == NULL)109 return -EINVAL;110 111 breq.ubuffer = bulkreq.ubuffer;112 breq.icount = bulkreq.icount;113 114 /*115 * FSBULKSTAT_SINGLE expects that *lastip contains the inode number116 * that we want to stat. However, FSINUMBERS and FSBULKSTAT expect117 * that *lastip contains either zero or the number of the last inode to118 * be examined by the previous call and return results starting with119 * the next inode after that. The new bulk request back end functions120 * take the inode to start with, so we have to compute the startino121 * parameter from lastino to maintain correct function. lastino == 0122 * is a special case because it has traditionally meant "first inode123 * in filesystem".124 */125 if (cmd == XFS_IOC_FSINUMBERS) {126 breq.startino = lastino ? lastino + 1 : 0;127 error = xfs_inumbers(&breq, xfs_fsinumbers_fmt);128 lastino = breq.startino - 1;129 } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {130 breq.startino = lastino;131 breq.icount = 1;132 error = xfs_bulkstat_one(&breq, xfs_fsbulkstat_one_fmt);133 } else { /* XFS_IOC_FSBULKSTAT */134 breq.startino = lastino ? lastino + 1 : 0;135 error = xfs_bulkstat(&breq, xfs_fsbulkstat_one_fmt);136 lastino = breq.startino - 1;137 }138 139 if (error)140 return error;141 142 if (bulkreq.lastip != NULL &&143 copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t)))144 return -EFAULT;145 146 if (bulkreq.ocount != NULL &&147 copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32)))148 return -EFAULT;149 150 return 0;151}152 153/* Return 0 on success or positive error */154static int155xfs_bulkstat_fmt(156 struct xfs_ibulk *breq,157 const struct xfs_bulkstat *bstat)158{159 if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat)))160 return -EFAULT;161 return xfs_ibulk_advance(breq, sizeof(struct xfs_bulkstat));162}163 164/*165 * Check the incoming bulk request @hdr from userspace and initialize the166 * internal @breq bulk request appropriately. Returns 0 if the bulk request167 * should proceed; -ECANCELED if there's nothing to do; or the usual168 * negative error code.169 */170static int171xfs_bulk_ireq_setup(172 struct xfs_mount *mp,173 const struct xfs_bulk_ireq *hdr,174 struct xfs_ibulk *breq,175 void __user *ubuffer)176{177 if (hdr->icount == 0 ||178 (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||179 memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))180 return -EINVAL;181 182 breq->startino = hdr->ino;183 breq->ubuffer = ubuffer;184 breq->icount = hdr->icount;185 breq->ocount = 0;186 breq->flags = 0;187 188 /*189 * The @ino parameter is a special value, so we must look it up here.190 * We're not allowed to have IREQ_AGNO, and we only return one inode191 * worth of data.192 */193 if (hdr->flags & XFS_BULK_IREQ_SPECIAL) {194 if (hdr->flags & XFS_BULK_IREQ_AGNO)195 return -EINVAL;196 197 switch (hdr->ino) {198 case XFS_BULK_IREQ_SPECIAL_ROOT:199 breq->startino = mp->m_sb.sb_rootino;200 break;201 default:202 return -EINVAL;203 }204 breq->icount = 1;205 }206 207 /*208 * The IREQ_AGNO flag means that we only want results from a given AG.209 * If @hdr->ino is zero, we start iterating in that AG. If @hdr->ino is210 * beyond the specified AG then we return no results.211 */212 if (hdr->flags & XFS_BULK_IREQ_AGNO) {213 if (hdr->agno >= mp->m_sb.sb_agcount)214 return -EINVAL;215 216 if (breq->startino == 0)217 breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);218 else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)219 return -EINVAL;220 221 breq->flags |= XFS_IBULK_SAME_AG;222 223 /* Asking for an inode past the end of the AG? We're done! */224 if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)225 return -ECANCELED;226 } else if (hdr->agno)227 return -EINVAL;228 229 /* Asking for an inode past the end of the FS? We're done! */230 if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)231 return -ECANCELED;232 233 if (hdr->flags & XFS_BULK_IREQ_NREXT64)234 breq->flags |= XFS_IBULK_NREXT64;235 236 return 0;237}238 239/*240 * Update the userspace bulk request @hdr to reflect the end state of the241 * internal bulk request @breq.242 */243static void244xfs_bulk_ireq_teardown(245 struct xfs_bulk_ireq *hdr,246 struct xfs_ibulk *breq)247{248 hdr->ino = breq->startino;249 hdr->ocount = breq->ocount;250}251 252/* Handle the v5 bulkstat ioctl. */253STATIC int254xfs_ioc_bulkstat(255 struct file *file,256 unsigned int cmd,257 struct xfs_bulkstat_req __user *arg)258{259 struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount;260 struct xfs_bulk_ireq hdr;261 struct xfs_ibulk breq = {262 .mp = mp,263 .idmap = file_mnt_idmap(file),264 };265 int error;266 267 if (!capable(CAP_SYS_ADMIN))268 return -EPERM;269 270 if (xfs_is_shutdown(mp))271 return -EIO;272 273 if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))274 return -EFAULT;275 276 error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);277 if (error == -ECANCELED)278 goto out_teardown;279 if (error < 0)280 return error;281 282 error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);283 if (error)284 return error;285 286out_teardown:287 xfs_bulk_ireq_teardown(&hdr, &breq);288 if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))289 return -EFAULT;290 291 return 0;292}293 294STATIC int295xfs_inumbers_fmt(296 struct xfs_ibulk *breq,297 const struct xfs_inumbers *igrp)298{299 if (copy_to_user(breq->ubuffer, igrp, sizeof(struct xfs_inumbers)))300 return -EFAULT;301 return xfs_ibulk_advance(breq, sizeof(struct xfs_inumbers));302}303 304/* Handle the v5 inumbers ioctl. */305STATIC int306xfs_ioc_inumbers(307 struct xfs_mount *mp,308 unsigned int cmd,309 struct xfs_inumbers_req __user *arg)310{311 struct xfs_bulk_ireq hdr;312 struct xfs_ibulk breq = {313 .mp = mp,314 };315 int error;316 317 if (!capable(CAP_SYS_ADMIN))318 return -EPERM;319 320 if (xfs_is_shutdown(mp))321 return -EIO;322 323 if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))324 return -EFAULT;325 326 error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->inumbers);327 if (error == -ECANCELED)328 goto out_teardown;329 if (error < 0)330 return error;331 332 error = xfs_inumbers(&breq, xfs_inumbers_fmt);333 if (error)334 return error;335 336out_teardown:337 xfs_bulk_ireq_teardown(&hdr, &breq);338 if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))339 return -EFAULT;340 341 return 0;342}343 344STATIC int345xfs_ioc_fsgeometry(346 struct xfs_mount *mp,347 void __user *arg,348 int struct_version)349{350 struct xfs_fsop_geom fsgeo;351 size_t len;352 353 xfs_fs_geometry(mp, &fsgeo, struct_version);354 355 if (struct_version <= 3)356 len = sizeof(struct xfs_fsop_geom_v1);357 else if (struct_version == 4)358 len = sizeof(struct xfs_fsop_geom_v4);359 else {360 xfs_fsop_geom_health(mp, &fsgeo);361 len = sizeof(fsgeo);362 }363 364 if (copy_to_user(arg, &fsgeo, len))365 return -EFAULT;366 return 0;367}368 369STATIC int370xfs_ioc_ag_geometry(371 struct xfs_mount *mp,372 void __user *arg)373{374 struct xfs_perag *pag;375 struct xfs_ag_geometry ageo;376 int error;377 378 if (copy_from_user(&ageo, arg, sizeof(ageo)))379 return -EFAULT;380 if (ageo.ag_flags)381 return -EINVAL;382 if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved)))383 return -EINVAL;384 385 pag = xfs_perag_get(mp, ageo.ag_number);386 if (!pag)387 return -EINVAL;388 389 error = xfs_ag_get_geometry(pag, &ageo);390 xfs_perag_put(pag);391 if (error)392 return error;393 394 if (copy_to_user(arg, &ageo, sizeof(ageo)))395 return -EFAULT;396 return 0;397}398 399/*400 * Linux extended inode flags interface.401 */402 403static void404xfs_fill_fsxattr(405 struct xfs_inode *ip,406 int whichfork,407 struct fileattr *fa)408{409 struct xfs_mount *mp = ip->i_mount;410 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);411 412 fileattr_fill_xflags(fa, xfs_ip2xflags(ip));413 414 if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) {415 fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);416 } else if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {417 /*418 * Don't let a misaligned extent size hint on a directory419 * escape to userspace if it won't pass the setattr checks420 * later.421 */422 if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&423 xfs_extlen_to_rtxmod(mp, ip->i_extsize) > 0) {424 fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE |425 FS_XFLAG_EXTSZINHERIT);426 fa->fsx_extsize = 0;427 } else {428 fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);429 }430 }431 432 if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)433 fa->fsx_cowextsize = XFS_FSB_TO_B(mp, ip->i_cowextsize);434 fa->fsx_projid = ip->i_projid;435 if (ifp && !xfs_need_iread_extents(ifp))436 fa->fsx_nextents = xfs_iext_count(ifp);437 else438 fa->fsx_nextents = xfs_ifork_nextents(ifp);439}440 441STATIC int442xfs_ioc_fsgetxattra(443 xfs_inode_t *ip,444 void __user *arg)445{446 struct fileattr fa;447 448 xfs_ilock(ip, XFS_ILOCK_SHARED);449 xfs_fill_fsxattr(ip, XFS_ATTR_FORK, &fa);450 xfs_iunlock(ip, XFS_ILOCK_SHARED);451 452 return copy_fsxattr_to_user(&fa, arg);453}454 455int456xfs_fileattr_get(457 struct dentry *dentry,458 struct fileattr *fa)459{460 struct xfs_inode *ip = XFS_I(d_inode(dentry));461 462 if (d_is_special(dentry))463 return -ENOTTY;464 465 xfs_ilock(ip, XFS_ILOCK_SHARED);466 xfs_fill_fsxattr(ip, XFS_DATA_FORK, fa);467 xfs_iunlock(ip, XFS_ILOCK_SHARED);468 469 return 0;470}471 472static int473xfs_ioctl_setattr_xflags(474 struct xfs_trans *tp,475 struct xfs_inode *ip,476 struct fileattr *fa)477{478 struct xfs_mount *mp = ip->i_mount;479 bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);480 uint64_t i_flags2;481 482 if (rtflag != XFS_IS_REALTIME_INODE(ip)) {483 /* Can't change realtime flag if any extents are allocated. */484 if (xfs_inode_has_filedata(ip))485 return -EINVAL;486 487 /*488 * If S_DAX is enabled on this file, we can only switch the489 * device if both support fsdax. We can't update S_DAX because490 * there might be other threads walking down the access paths.491 */492 if (IS_DAX(VFS_I(ip)) &&493 (mp->m_ddev_targp->bt_daxdev == NULL ||494 (mp->m_rtdev_targp &&495 mp->m_rtdev_targp->bt_daxdev == NULL)))496 return -EINVAL;497 }498 499 if (rtflag) {500 /* If realtime flag is set then must have realtime device */501 if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||502 xfs_extlen_to_rtxmod(mp, ip->i_extsize))503 return -EINVAL;504 505 /* Clear reflink if we are actually able to set the rt flag. */506 if (xfs_is_reflink_inode(ip))507 ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;508 }509 510 /* diflags2 only valid for v3 inodes. */511 i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);512 if (i_flags2 && !xfs_has_v3inodes(mp))513 return -EINVAL;514 515 ip->i_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);516 ip->i_diflags2 = i_flags2;517 518 xfs_diflags_to_iflags(ip, false);519 520 /*521 * Make the stable writes flag match that of the device the inode522 * resides on when flipping the RT flag.523 */524 if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode))525 xfs_update_stable_writes(ip);526 527 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);528 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);529 XFS_STATS_INC(mp, xs_ig_attrchg);530 return 0;531}532 533static void534xfs_ioctl_setattr_prepare_dax(535 struct xfs_inode *ip,536 struct fileattr *fa)537{538 struct xfs_mount *mp = ip->i_mount;539 struct inode *inode = VFS_I(ip);540 541 if (S_ISDIR(inode->i_mode))542 return;543 544 if (xfs_has_dax_always(mp) || xfs_has_dax_never(mp))545 return;546 547 if (((fa->fsx_xflags & FS_XFLAG_DAX) &&548 !(ip->i_diflags2 & XFS_DIFLAG2_DAX)) ||549 (!(fa->fsx_xflags & FS_XFLAG_DAX) &&550 (ip->i_diflags2 & XFS_DIFLAG2_DAX)))551 d_mark_dontcache(inode);552}553 554/*555 * Set up the transaction structure for the setattr operation, checking that we556 * have permission to do so. On success, return a clean transaction and the557 * inode locked exclusively ready for further operation specific checks. On558 * failure, return an error without modifying or locking the inode.559 */560static struct xfs_trans *561xfs_ioctl_setattr_get_trans(562 struct xfs_inode *ip,563 struct xfs_dquot *pdqp)564{565 struct xfs_mount *mp = ip->i_mount;566 struct xfs_trans *tp;567 int error = -EROFS;568 569 if (xfs_is_readonly(mp))570 goto out_error;571 error = -EIO;572 if (xfs_is_shutdown(mp))573 goto out_error;574 575 error = xfs_trans_alloc_ichange(ip, NULL, NULL, pdqp,576 has_capability_noaudit(current, CAP_FOWNER), &tp);577 if (error)578 goto out_error;579 580 if (xfs_has_wsync(mp))581 xfs_trans_set_sync(tp);582 583 return tp;584 585out_error:586 return ERR_PTR(error);587}588 589/*590 * Validate a proposed extent size hint. For regular files, the hint can only591 * be changed if no extents are allocated.592 */593static int594xfs_ioctl_setattr_check_extsize(595 struct xfs_inode *ip,596 struct fileattr *fa)597{598 struct xfs_mount *mp = ip->i_mount;599 xfs_failaddr_t failaddr;600 uint16_t new_diflags;601 602 if (!fa->fsx_valid)603 return 0;604 605 if (S_ISREG(VFS_I(ip)->i_mode) && xfs_inode_has_filedata(ip) &&606 XFS_FSB_TO_B(mp, ip->i_extsize) != fa->fsx_extsize)607 return -EINVAL;608 609 if (fa->fsx_extsize & mp->m_blockmask)610 return -EINVAL;611 612 new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);613 614 /*615 * Inode verifiers do not check that the extent size hint is an integer616 * multiple of the rt extent size on a directory with both rtinherit617 * and extszinherit flags set. Don't let sysadmins misconfigure618 * directories.619 */620 if ((new_diflags & XFS_DIFLAG_RTINHERIT) &&621 (new_diflags & XFS_DIFLAG_EXTSZINHERIT)) {622 unsigned int rtextsize_bytes;623 624 rtextsize_bytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);625 if (fa->fsx_extsize % rtextsize_bytes)626 return -EINVAL;627 }628 629 failaddr = xfs_inode_validate_extsize(ip->i_mount,630 XFS_B_TO_FSB(mp, fa->fsx_extsize),631 VFS_I(ip)->i_mode, new_diflags);632 return failaddr != NULL ? -EINVAL : 0;633}634 635static int636xfs_ioctl_setattr_check_cowextsize(637 struct xfs_inode *ip,638 struct fileattr *fa)639{640 struct xfs_mount *mp = ip->i_mount;641 xfs_failaddr_t failaddr;642 uint64_t new_diflags2;643 uint16_t new_diflags;644 645 if (!fa->fsx_valid)646 return 0;647 648 if (fa->fsx_cowextsize & mp->m_blockmask)649 return -EINVAL;650 651 new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);652 new_diflags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);653 654 failaddr = xfs_inode_validate_cowextsize(ip->i_mount,655 XFS_B_TO_FSB(mp, fa->fsx_cowextsize),656 VFS_I(ip)->i_mode, new_diflags, new_diflags2);657 return failaddr != NULL ? -EINVAL : 0;658}659 660static int661xfs_ioctl_setattr_check_projid(662 struct xfs_inode *ip,663 struct fileattr *fa)664{665 if (!fa->fsx_valid)666 return 0;667 668 /* Disallow 32bit project ids if 32bit IDs are not enabled. */669 if (fa->fsx_projid > (uint16_t)-1 &&670 !xfs_has_projid32(ip->i_mount))671 return -EINVAL;672 return 0;673}674 675int676xfs_fileattr_set(677 struct mnt_idmap *idmap,678 struct dentry *dentry,679 struct fileattr *fa)680{681 struct xfs_inode *ip = XFS_I(d_inode(dentry));682 struct xfs_mount *mp = ip->i_mount;683 struct xfs_trans *tp;684 struct xfs_dquot *pdqp = NULL;685 struct xfs_dquot *olddquot = NULL;686 int error;687 688 trace_xfs_ioctl_setattr(ip);689 690 if (d_is_special(dentry))691 return -ENOTTY;692 693 if (!fa->fsx_valid) {694 if (fa->flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL |695 FS_NOATIME_FL | FS_NODUMP_FL |696 FS_SYNC_FL | FS_DAX_FL | FS_PROJINHERIT_FL))697 return -EOPNOTSUPP;698 }699 700 error = xfs_ioctl_setattr_check_projid(ip, fa);701 if (error)702 return error;703 704 /*705 * If disk quotas is on, we make sure that the dquots do exist on disk,706 * before we start any other transactions. Trying to do this later707 * is messy. We don't care to take a readlock to look at the ids708 * in inode here, because we can't hold it across the trans_reserve.709 * If the IDs do change before we take the ilock, we're covered710 * because the i_*dquot fields will get updated anyway.711 */712 if (fa->fsx_valid && XFS_IS_QUOTA_ON(mp)) {713 error = xfs_qm_vop_dqalloc(ip, VFS_I(ip)->i_uid,714 VFS_I(ip)->i_gid, fa->fsx_projid,715 XFS_QMOPT_PQUOTA, NULL, NULL, &pdqp);716 if (error)717 return error;718 }719 720 xfs_ioctl_setattr_prepare_dax(ip, fa);721 722 tp = xfs_ioctl_setattr_get_trans(ip, pdqp);723 if (IS_ERR(tp)) {724 error = PTR_ERR(tp);725 goto error_free_dquots;726 }727 728 error = xfs_ioctl_setattr_check_extsize(ip, fa);729 if (error)730 goto error_trans_cancel;731 732 error = xfs_ioctl_setattr_check_cowextsize(ip, fa);733 if (error)734 goto error_trans_cancel;735 736 error = xfs_ioctl_setattr_xflags(tp, ip, fa);737 if (error)738 goto error_trans_cancel;739 740 if (!fa->fsx_valid)741 goto skip_xattr;742 /*743 * Change file ownership. Must be the owner or privileged. CAP_FSETID744 * overrides the following restrictions:745 *746 * The set-user-ID and set-group-ID bits of a file will be cleared upon747 * successful return from chown()748 */749 750 if ((VFS_I(ip)->i_mode & (S_ISUID|S_ISGID)) &&751 !capable_wrt_inode_uidgid(idmap, VFS_I(ip), CAP_FSETID))752 VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);753 754 /* Change the ownerships and register project quota modifications */755 if (ip->i_projid != fa->fsx_projid) {756 if (XFS_IS_PQUOTA_ON(mp)) {757 olddquot = xfs_qm_vop_chown(tp, ip,758 &ip->i_pdquot, pdqp);759 }760 ip->i_projid = fa->fsx_projid;761 }762 763 /*764 * Only set the extent size hint if we've already determined that the765 * extent size hint should be set on the inode. If no extent size flags766 * are set on the inode then unconditionally clear the extent size hint.767 */768 if (ip->i_diflags & (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))769 ip->i_extsize = XFS_B_TO_FSB(mp, fa->fsx_extsize);770 else771 ip->i_extsize = 0;772 773 if (xfs_has_v3inodes(mp)) {774 if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)775 ip->i_cowextsize = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);776 else777 ip->i_cowextsize = 0;778 }779 780skip_xattr:781 error = xfs_trans_commit(tp);782 783 /*784 * Release any dquot(s) the inode had kept before chown.785 */786 xfs_qm_dqrele(olddquot);787 xfs_qm_dqrele(pdqp);788 789 return error;790 791error_trans_cancel:792 xfs_trans_cancel(tp);793error_free_dquots:794 xfs_qm_dqrele(pdqp);795 return error;796}797 798static bool799xfs_getbmap_format(800 struct kgetbmap *p,801 struct getbmapx __user *u,802 size_t recsize)803{804 if (put_user(p->bmv_offset, &u->bmv_offset) ||805 put_user(p->bmv_block, &u->bmv_block) ||806 put_user(p->bmv_length, &u->bmv_length) ||807 put_user(0, &u->bmv_count) ||808 put_user(0, &u->bmv_entries))809 return false;810 if (recsize < sizeof(struct getbmapx))811 return true;812 if (put_user(0, &u->bmv_iflags) ||813 put_user(p->bmv_oflags, &u->bmv_oflags) ||814 put_user(0, &u->bmv_unused1) ||815 put_user(0, &u->bmv_unused2))816 return false;817 return true;818}819 820STATIC int821xfs_ioc_getbmap(822 struct file *file,823 unsigned int cmd,824 void __user *arg)825{826 struct getbmapx bmx = { 0 };827 struct kgetbmap *buf;828 size_t recsize;829 int error, i;830 831 switch (cmd) {832 case XFS_IOC_GETBMAPA:833 bmx.bmv_iflags = BMV_IF_ATTRFORK;834 fallthrough;835 case XFS_IOC_GETBMAP:836 /* struct getbmap is a strict subset of struct getbmapx. */837 recsize = sizeof(struct getbmap);838 break;839 case XFS_IOC_GETBMAPX:840 recsize = sizeof(struct getbmapx);841 break;842 default:843 return -EINVAL;844 }845 846 if (copy_from_user(&bmx, arg, recsize))847 return -EFAULT;848 849 if (bmx.bmv_count < 2)850 return -EINVAL;851 if (bmx.bmv_count >= INT_MAX / recsize)852 return -ENOMEM;853 854 buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL);855 if (!buf)856 return -ENOMEM;857 858 error = xfs_getbmap(XFS_I(file_inode(file)), &bmx, buf);859 if (error)860 goto out_free_buf;861 862 error = -EFAULT;863 if (copy_to_user(arg, &bmx, recsize))864 goto out_free_buf;865 arg += recsize;866 867 for (i = 0; i < bmx.bmv_entries; i++) {868 if (!xfs_getbmap_format(buf + i, arg, recsize))869 goto out_free_buf;870 arg += recsize;871 }872 873 error = 0;874out_free_buf:875 kvfree(buf);876 return error;877}878 879int880xfs_ioc_swapext(881 xfs_swapext_t *sxp)882{883 xfs_inode_t *ip, *tip;884 struct fd f, tmp;885 int error = 0;886 887 /* Pull information for the target fd */888 f = fdget((int)sxp->sx_fdtarget);889 if (!fd_file(f)) {890 error = -EINVAL;891 goto out;892 }893 894 if (!(fd_file(f)->f_mode & FMODE_WRITE) ||895 !(fd_file(f)->f_mode & FMODE_READ) ||896 (fd_file(f)->f_flags & O_APPEND)) {897 error = -EBADF;898 goto out_put_file;899 }900 901 tmp = fdget((int)sxp->sx_fdtmp);902 if (!fd_file(tmp)) {903 error = -EINVAL;904 goto out_put_file;905 }906 907 if (!(fd_file(tmp)->f_mode & FMODE_WRITE) ||908 !(fd_file(tmp)->f_mode & FMODE_READ) ||909 (fd_file(tmp)->f_flags & O_APPEND)) {910 error = -EBADF;911 goto out_put_tmp_file;912 }913 914 if (IS_SWAPFILE(file_inode(fd_file(f))) ||915 IS_SWAPFILE(file_inode(fd_file(tmp)))) {916 error = -EINVAL;917 goto out_put_tmp_file;918 }919 920 /*921 * We need to ensure that the fds passed in point to XFS inodes922 * before we cast and access them as XFS structures as we have no923 * control over what the user passes us here.924 */925 if (fd_file(f)->f_op != &xfs_file_operations ||926 fd_file(tmp)->f_op != &xfs_file_operations) {927 error = -EINVAL;928 goto out_put_tmp_file;929 }930 931 ip = XFS_I(file_inode(fd_file(f)));932 tip = XFS_I(file_inode(fd_file(tmp)));933 934 if (ip->i_mount != tip->i_mount) {935 error = -EINVAL;936 goto out_put_tmp_file;937 }938 939 if (ip->i_ino == tip->i_ino) {940 error = -EINVAL;941 goto out_put_tmp_file;942 }943 944 if (xfs_is_shutdown(ip->i_mount)) {945 error = -EIO;946 goto out_put_tmp_file;947 }948 949 error = xfs_swap_extents(ip, tip, sxp);950 951 out_put_tmp_file:952 fdput(tmp);953 out_put_file:954 fdput(f);955 out:956 return error;957}958 959static int960xfs_ioc_getlabel(961 struct xfs_mount *mp,962 char __user *user_label)963{964 struct xfs_sb *sbp = &mp->m_sb;965 char label[XFSLABEL_MAX + 1];966 967 /* Paranoia */968 BUILD_BUG_ON(sizeof(sbp->sb_fname) > FSLABEL_MAX);969 970 /* 1 larger than sb_fname, so this ensures a trailing NUL char */971 memset(label, 0, sizeof(label));972 spin_lock(&mp->m_sb_lock);973 strncpy(label, sbp->sb_fname, XFSLABEL_MAX);974 spin_unlock(&mp->m_sb_lock);975 976 if (copy_to_user(user_label, label, sizeof(label)))977 return -EFAULT;978 return 0;979}980 981static int982xfs_ioc_setlabel(983 struct file *filp,984 struct xfs_mount *mp,985 char __user *newlabel)986{987 struct xfs_sb *sbp = &mp->m_sb;988 char label[XFSLABEL_MAX + 1];989 size_t len;990 int error;991 992 if (!capable(CAP_SYS_ADMIN))993 return -EPERM;994 /*995 * The generic ioctl allows up to FSLABEL_MAX chars, but XFS is much996 * smaller, at 12 bytes. We copy one more to be sure we find the997 * (required) NULL character to test the incoming label length.998 * NB: The on disk label doesn't need to be null terminated.999 */1000 if (copy_from_user(label, newlabel, XFSLABEL_MAX + 1))1001 return -EFAULT;1002 len = strnlen(label, XFSLABEL_MAX + 1);1003 if (len > sizeof(sbp->sb_fname))1004 return -EINVAL;1005 1006 error = mnt_want_write_file(filp);1007 if (error)1008 return error;1009 1010 spin_lock(&mp->m_sb_lock);1011 memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname));1012 memcpy(sbp->sb_fname, label, len);1013 spin_unlock(&mp->m_sb_lock);1014 1015 /*1016 * Now we do several things to satisfy userspace.1017 * In addition to normal logging of the primary superblock, we also1018 * immediately write these changes to sector zero for the primary, then1019 * update all backup supers (as xfs_db does for a label change), then1020 * invalidate the block device page cache. This is so that any prior1021 * buffered reads from userspace (i.e. from blkid) are invalidated,1022 * and userspace will see the newly-written label.1023 */1024 error = xfs_sync_sb_buf(mp);1025 if (error)1026 goto out;1027 /*1028 * growfs also updates backup supers so lock against that.1029 */1030 mutex_lock(&mp->m_growlock);1031 error = xfs_update_secondary_sbs(mp);1032 mutex_unlock(&mp->m_growlock);1033 1034 invalidate_bdev(mp->m_ddev_targp->bt_bdev);1035 1036out:1037 mnt_drop_write_file(filp);1038 return error;1039}1040 1041static inline int1042xfs_fs_eofblocks_from_user(1043 struct xfs_fs_eofblocks *src,1044 struct xfs_icwalk *dst)1045{1046 if (src->eof_version != XFS_EOFBLOCKS_VERSION)1047 return -EINVAL;1048 1049 if (src->eof_flags & ~XFS_EOF_FLAGS_VALID)1050 return -EINVAL;1051 1052 if (memchr_inv(&src->pad32, 0, sizeof(src->pad32)) ||1053 memchr_inv(src->pad64, 0, sizeof(src->pad64)))1054 return -EINVAL;1055 1056 dst->icw_flags = 0;1057 if (src->eof_flags & XFS_EOF_FLAGS_SYNC)1058 dst->icw_flags |= XFS_ICWALK_FLAG_SYNC;1059 if (src->eof_flags & XFS_EOF_FLAGS_UID)1060 dst->icw_flags |= XFS_ICWALK_FLAG_UID;1061 if (src->eof_flags & XFS_EOF_FLAGS_GID)1062 dst->icw_flags |= XFS_ICWALK_FLAG_GID;1063 if (src->eof_flags & XFS_EOF_FLAGS_PRID)1064 dst->icw_flags |= XFS_ICWALK_FLAG_PRID;1065 if (src->eof_flags & XFS_EOF_FLAGS_MINFILESIZE)1066 dst->icw_flags |= XFS_ICWALK_FLAG_MINFILESIZE;1067 1068 dst->icw_prid = src->eof_prid;1069 dst->icw_min_file_size = src->eof_min_file_size;1070 1071 dst->icw_uid = INVALID_UID;1072 if (src->eof_flags & XFS_EOF_FLAGS_UID) {1073 dst->icw_uid = make_kuid(current_user_ns(), src->eof_uid);1074 if (!uid_valid(dst->icw_uid))1075 return -EINVAL;1076 }1077 1078 dst->icw_gid = INVALID_GID;1079 if (src->eof_flags & XFS_EOF_FLAGS_GID) {1080 dst->icw_gid = make_kgid(current_user_ns(), src->eof_gid);1081 if (!gid_valid(dst->icw_gid))1082 return -EINVAL;1083 }1084 return 0;1085}1086 1087static int1088xfs_ioctl_getset_resblocks(1089 struct file *filp,1090 unsigned int cmd,1091 void __user *arg)1092{1093 struct xfs_mount *mp = XFS_I(file_inode(filp))->i_mount;1094 struct xfs_fsop_resblks fsop = { };1095 int error;1096 1097 if (!capable(CAP_SYS_ADMIN))1098 return -EPERM;1099 1100 if (cmd == XFS_IOC_SET_RESBLKS) {1101 if (xfs_is_readonly(mp))1102 return -EROFS;1103 1104 if (copy_from_user(&fsop, arg, sizeof(fsop)))1105 return -EFAULT;1106 1107 error = mnt_want_write_file(filp);1108 if (error)1109 return error;1110 error = xfs_reserve_blocks(mp, fsop.resblks);1111 mnt_drop_write_file(filp);1112 if (error)1113 return error;1114 }1115 1116 spin_lock(&mp->m_sb_lock);1117 fsop.resblks = mp->m_resblks;1118 fsop.resblks_avail = mp->m_resblks_avail;1119 spin_unlock(&mp->m_sb_lock);1120 1121 if (copy_to_user(arg, &fsop, sizeof(fsop)))1122 return -EFAULT;1123 return 0;1124}1125 1126static int1127xfs_ioctl_fs_counts(1128 struct xfs_mount *mp,1129 struct xfs_fsop_counts __user *uarg)1130{1131 struct xfs_fsop_counts out = {1132 .allocino = percpu_counter_read_positive(&mp->m_icount),1133 .freeino = percpu_counter_read_positive(&mp->m_ifree),1134 .freedata = percpu_counter_read_positive(&mp->m_fdblocks) -1135 xfs_fdblocks_unavailable(mp),1136 .freertx = percpu_counter_read_positive(&mp->m_frextents),1137 };1138 1139 if (copy_to_user(uarg, &out, sizeof(out)))1140 return -EFAULT;1141 return 0;1142}1143 1144/*1145 * These long-unused ioctls were removed from the official ioctl API in 5.17,1146 * but retain these definitions so that we can log warnings about them.1147 */1148#define XFS_IOC_ALLOCSP _IOW ('X', 10, struct xfs_flock64)1149#define XFS_IOC_FREESP _IOW ('X', 11, struct xfs_flock64)1150#define XFS_IOC_ALLOCSP64 _IOW ('X', 36, struct xfs_flock64)1151#define XFS_IOC_FREESP64 _IOW ('X', 37, struct xfs_flock64)1152 1153/*1154 * Note: some of the ioctl's return positive numbers as a1155 * byte count indicating success, such as readlink_by_handle.1156 * So we don't "sign flip" like most other routines. This means1157 * true errors need to be returned as a negative value.1158 */1159long1160xfs_file_ioctl(1161 struct file *filp,1162 unsigned int cmd,1163 unsigned long p)1164{1165 struct inode *inode = file_inode(filp);1166 struct xfs_inode *ip = XFS_I(inode);1167 struct xfs_mount *mp = ip->i_mount;1168 void __user *arg = (void __user *)p;1169 int error;1170 1171 trace_xfs_file_ioctl(ip);1172 1173 switch (cmd) {1174 case FITRIM:1175 return xfs_ioc_trim(mp, arg);1176 case FS_IOC_GETFSLABEL:1177 return xfs_ioc_getlabel(mp, arg);1178 case FS_IOC_SETFSLABEL:1179 return xfs_ioc_setlabel(filp, mp, arg);1180 case XFS_IOC_ALLOCSP:1181 case XFS_IOC_FREESP:1182 case XFS_IOC_ALLOCSP64:1183 case XFS_IOC_FREESP64:1184 xfs_warn_once(mp,1185 "%s should use fallocate; XFS_IOC_{ALLOC,FREE}SP ioctl unsupported",1186 current->comm);1187 return -ENOTTY;1188 case XFS_IOC_DIOINFO: {1189 struct xfs_buftarg *target = xfs_inode_buftarg(ip);1190 struct dioattr da;1191 1192 da.d_mem = da.d_miniosz = target->bt_logical_sectorsize;1193 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);1194 1195 if (copy_to_user(arg, &da, sizeof(da)))1196 return -EFAULT;1197 return 0;1198 }1199 1200 case XFS_IOC_FSBULKSTAT_SINGLE:1201 case XFS_IOC_FSBULKSTAT:1202 case XFS_IOC_FSINUMBERS:1203 return xfs_ioc_fsbulkstat(filp, cmd, arg);1204 1205 case XFS_IOC_BULKSTAT:1206 return xfs_ioc_bulkstat(filp, cmd, arg);1207 case XFS_IOC_INUMBERS:1208 return xfs_ioc_inumbers(mp, cmd, arg);1209 1210 case XFS_IOC_FSGEOMETRY_V1:1211 return xfs_ioc_fsgeometry(mp, arg, 3);1212 case XFS_IOC_FSGEOMETRY_V4:1213 return xfs_ioc_fsgeometry(mp, arg, 4);1214 case XFS_IOC_FSGEOMETRY:1215 return xfs_ioc_fsgeometry(mp, arg, 5);1216 1217 case XFS_IOC_AG_GEOMETRY:1218 return xfs_ioc_ag_geometry(mp, arg);1219 1220 case XFS_IOC_GETVERSION:1221 return put_user(inode->i_generation, (int __user *)arg);1222 1223 case XFS_IOC_FSGETXATTRA:1224 return xfs_ioc_fsgetxattra(ip, arg);1225 case XFS_IOC_GETPARENTS:1226 return xfs_ioc_getparents(filp, arg);1227 case XFS_IOC_GETPARENTS_BY_HANDLE:1228 return xfs_ioc_getparents_by_handle(filp, arg);1229 case XFS_IOC_GETBMAP:1230 case XFS_IOC_GETBMAPA:1231 case XFS_IOC_GETBMAPX:1232 return xfs_ioc_getbmap(filp, cmd, arg);1233 1234 case FS_IOC_GETFSMAP:1235 return xfs_ioc_getfsmap(ip, arg);1236 1237 case XFS_IOC_SCRUBV_METADATA:1238 return xfs_ioc_scrubv_metadata(filp, arg);1239 case XFS_IOC_SCRUB_METADATA:1240 return xfs_ioc_scrub_metadata(filp, arg);1241 1242 case XFS_IOC_FD_TO_HANDLE:1243 case XFS_IOC_PATH_TO_HANDLE:1244 case XFS_IOC_PATH_TO_FSHANDLE: {1245 xfs_fsop_handlereq_t hreq;1246 1247 if (copy_from_user(&hreq, arg, sizeof(hreq)))1248 return -EFAULT;1249 return xfs_find_handle(cmd, &hreq);1250 }1251 case XFS_IOC_OPEN_BY_HANDLE: {1252 xfs_fsop_handlereq_t hreq;1253 1254 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))1255 return -EFAULT;1256 return xfs_open_by_handle(filp, &hreq);1257 }1258 1259 case XFS_IOC_READLINK_BY_HANDLE: {1260 xfs_fsop_handlereq_t hreq;1261 1262 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))1263 return -EFAULT;1264 return xfs_readlink_by_handle(filp, &hreq);1265 }1266 case XFS_IOC_ATTRLIST_BY_HANDLE:1267 return xfs_attrlist_by_handle(filp, arg);1268 1269 case XFS_IOC_ATTRMULTI_BY_HANDLE:1270 return xfs_attrmulti_by_handle(filp, arg);1271 1272 case XFS_IOC_SWAPEXT: {1273 struct xfs_swapext sxp;1274 1275 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))1276 return -EFAULT;1277 error = mnt_want_write_file(filp);1278 if (error)1279 return error;1280 error = xfs_ioc_swapext(&sxp);1281 mnt_drop_write_file(filp);1282 return error;1283 }1284 1285 case XFS_IOC_FSCOUNTS:1286 return xfs_ioctl_fs_counts(mp, arg);1287 1288 case XFS_IOC_SET_RESBLKS:1289 case XFS_IOC_GET_RESBLKS:1290 return xfs_ioctl_getset_resblocks(filp, cmd, arg);1291 1292 case XFS_IOC_FSGROWFSDATA: {1293 struct xfs_growfs_data in;1294 1295 if (copy_from_user(&in, arg, sizeof(in)))1296 return -EFAULT;1297 1298 error = mnt_want_write_file(filp);1299 if (error)1300 return error;1301 error = xfs_growfs_data(mp, &in);1302 mnt_drop_write_file(filp);1303 return error;1304 }1305 1306 case XFS_IOC_FSGROWFSLOG: {1307 struct xfs_growfs_log in;1308 1309 if (copy_from_user(&in, arg, sizeof(in)))1310 return -EFAULT;1311 1312 error = mnt_want_write_file(filp);1313 if (error)1314 return error;1315 error = xfs_growfs_log(mp, &in);1316 mnt_drop_write_file(filp);1317 return error;1318 }1319 1320 case XFS_IOC_FSGROWFSRT: {1321 xfs_growfs_rt_t in;1322 1323 if (copy_from_user(&in, arg, sizeof(in)))1324 return -EFAULT;1325 1326 error = mnt_want_write_file(filp);1327 if (error)1328 return error;1329 error = xfs_growfs_rt(mp, &in);1330 mnt_drop_write_file(filp);1331 return error;1332 }1333 1334 case XFS_IOC_GOINGDOWN: {1335 uint32_t in;1336 1337 if (!capable(CAP_SYS_ADMIN))1338 return -EPERM;1339 1340 if (get_user(in, (uint32_t __user *)arg))1341 return -EFAULT;1342 1343 return xfs_fs_goingdown(mp, in);1344 }1345 1346 case XFS_IOC_ERROR_INJECTION: {1347 xfs_error_injection_t in;1348 1349 if (!capable(CAP_SYS_ADMIN))1350 return -EPERM;1351 1352 if (copy_from_user(&in, arg, sizeof(in)))1353 return -EFAULT;1354 1355 return xfs_errortag_add(mp, in.errtag);1356 }1357 1358 case XFS_IOC_ERROR_CLEARALL:1359 if (!capable(CAP_SYS_ADMIN))1360 return -EPERM;1361 1362 return xfs_errortag_clearall(mp);1363 1364 case XFS_IOC_FREE_EOFBLOCKS: {1365 struct xfs_fs_eofblocks eofb;1366 struct xfs_icwalk icw;1367 1368 if (!capable(CAP_SYS_ADMIN))1369 return -EPERM;1370 1371 if (xfs_is_readonly(mp))1372 return -EROFS;1373 1374 if (copy_from_user(&eofb, arg, sizeof(eofb)))1375 return -EFAULT;1376 1377 error = xfs_fs_eofblocks_from_user(&eofb, &icw);1378 if (error)1379 return error;1380 1381 trace_xfs_ioc_free_eofblocks(mp, &icw, _RET_IP_);1382 1383 sb_start_write(mp->m_super);1384 error = xfs_blockgc_free_space(mp, &icw);1385 sb_end_write(mp->m_super);1386 return error;1387 }1388 1389 case XFS_IOC_EXCHANGE_RANGE:1390 return xfs_ioc_exchange_range(filp, arg);1391 case XFS_IOC_START_COMMIT:1392 return xfs_ioc_start_commit(filp, arg);1393 case XFS_IOC_COMMIT_RANGE:1394 return xfs_ioc_commit_range(filp, arg);1395 1396 default:1397 return -ENOTTY;1398 }1399}1400