Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: Propagate dentry down to inode_change_ok()

To avoid clearing of capabilities or security related extended
attributes too early, inode_change_ok() will need to take dentry instead
of inode. Propagate dentry down to functions calling inode_change_ok().
This is rather straightforward except for xfs_set_mode() function which
does not have dentry easily available. Luckily that function does not
call inode_change_ok() anyway so we just have to do a little dance with
function prototypes.

Acked-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>

Jan Kara 69bca807 07393101

+68 -35
+1 -1
fs/xfs/xfs_file.c
··· 973 973 974 974 iattr.ia_valid = ATTR_SIZE; 975 975 iattr.ia_size = new_size; 976 - error = xfs_setattr_size(ip, &iattr); 976 + error = xfs_vn_setattr_size(file_dentry(file), &iattr); 977 977 if (error) 978 978 goto out_unlock; 979 979 }
+1 -1
fs/xfs/xfs_inode.c
··· 1710 1710 /* 1711 1711 * Log the inode size first to prevent stale data exposure in the event 1712 1712 * of a system crash before the truncate completes. See the related 1713 - * comment in xfs_setattr_size() for details. 1713 + * comment in xfs_vn_setattr_size() for details. 1714 1714 */ 1715 1715 ip->i_d.di_size = 0; 1716 1716 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+1 -1
fs/xfs/xfs_ioctl.c
··· 720 720 iattr.ia_valid = ATTR_SIZE; 721 721 iattr.ia_size = bf->l_start; 722 722 723 - error = xfs_setattr_size(ip, &iattr); 723 + error = xfs_vn_setattr_size(file_dentry(filp), &iattr); 724 724 break; 725 725 default: 726 726 ASSERT(0);
+63 -31
fs/xfs/xfs_iops.c
··· 542 542 inode->i_mtime = iattr->ia_mtime; 543 543 } 544 544 545 + static int 546 + xfs_vn_change_ok( 547 + struct dentry *dentry, 548 + struct iattr *iattr) 549 + { 550 + struct inode *inode = d_inode(dentry); 551 + struct xfs_inode *ip = XFS_I(inode); 552 + struct xfs_mount *mp = ip->i_mount; 553 + 554 + if (mp->m_flags & XFS_MOUNT_RDONLY) 555 + return -EROFS; 556 + 557 + if (XFS_FORCED_SHUTDOWN(mp)) 558 + return -EIO; 559 + 560 + return inode_change_ok(inode, iattr); 561 + } 562 + 563 + /* 564 + * Set non-size attributes of an inode. 565 + * 566 + * Caution: The caller of this function is responsible for calling 567 + * inode_change_ok() or otherwise verifying the change is fine. 568 + */ 545 569 int 546 570 xfs_setattr_nonsize( 547 571 struct xfs_inode *ip, ··· 581 557 kgid_t gid = GLOBAL_ROOT_GID, igid = GLOBAL_ROOT_GID; 582 558 struct xfs_dquot *udqp = NULL, *gdqp = NULL; 583 559 struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; 584 - 585 - trace_xfs_setattr(ip); 586 - 587 - /* If acls are being inherited, we already have this checked */ 588 - if (!(flags & XFS_ATTR_NOACL)) { 589 - if (mp->m_flags & XFS_MOUNT_RDONLY) 590 - return -EROFS; 591 - 592 - if (XFS_FORCED_SHUTDOWN(mp)) 593 - return -EIO; 594 - 595 - error = inode_change_ok(inode, iattr); 596 - if (error) 597 - return error; 598 - } 599 560 600 561 ASSERT((mask & ATTR_SIZE) == 0); 601 562 ··· 752 743 return error; 753 744 } 754 745 746 + int 747 + xfs_vn_setattr_nonsize( 748 + struct dentry *dentry, 749 + struct iattr *iattr) 750 + { 751 + struct xfs_inode *ip = XFS_I(d_inode(dentry)); 752 + int error; 753 + 754 + trace_xfs_setattr(ip); 755 + 756 + error = xfs_vn_change_ok(dentry, iattr); 757 + if (error) 758 + return error; 759 + return xfs_setattr_nonsize(ip, iattr, 0); 760 + } 761 + 755 762 /* 756 763 * Truncate file. Must have write permission and not be a directory. 764 + * 765 + * Caution: The caller of this function is responsible for calling 766 + * inode_change_ok() or otherwise verifying the change is fine. 757 767 */ 758 768 int 759 769 xfs_setattr_size( ··· 786 758 int error; 787 759 uint lock_flags = 0; 788 760 bool did_zeroing = false; 789 - 790 - trace_xfs_setattr(ip); 791 - 792 - if (mp->m_flags & XFS_MOUNT_RDONLY) 793 - return -EROFS; 794 - 795 - if (XFS_FORCED_SHUTDOWN(mp)) 796 - return -EIO; 797 - 798 - error = inode_change_ok(inode, iattr); 799 - if (error) 800 - return error; 801 761 802 762 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); 803 763 ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); ··· 958 942 goto out_unlock; 959 943 } 960 944 945 + int 946 + xfs_vn_setattr_size( 947 + struct dentry *dentry, 948 + struct iattr *iattr) 949 + { 950 + struct xfs_inode *ip = XFS_I(d_inode(dentry)); 951 + int error; 952 + 953 + trace_xfs_setattr(ip); 954 + 955 + error = xfs_vn_change_ok(dentry, iattr); 956 + if (error) 957 + return error; 958 + return xfs_setattr_size(ip, iattr); 959 + } 960 + 961 961 STATIC int 962 962 xfs_vn_setattr( 963 963 struct dentry *dentry, 964 964 struct iattr *iattr) 965 965 { 966 - struct xfs_inode *ip = XFS_I(d_inode(dentry)); 967 966 int error; 968 967 969 968 if (iattr->ia_valid & ATTR_SIZE) { 970 - uint iolock = XFS_IOLOCK_EXCL; 969 + struct xfs_inode *ip = XFS_I(d_inode(dentry)); 970 + uint iolock = XFS_IOLOCK_EXCL; 971 971 972 972 xfs_ilock(ip, iolock); 973 973 error = xfs_break_layouts(d_inode(dentry), &iolock, true); ··· 991 959 xfs_ilock(ip, XFS_MMAPLOCK_EXCL); 992 960 iolock |= XFS_MMAPLOCK_EXCL; 993 961 994 - error = xfs_setattr_size(ip, iattr); 962 + error = xfs_vn_setattr_size(dentry, iattr); 995 963 } 996 964 xfs_iunlock(ip, iolock); 997 965 } else { 998 - error = xfs_setattr_nonsize(ip, iattr, 0); 966 + error = xfs_vn_setattr_nonsize(dentry, iattr); 999 967 } 1000 968 1001 969 return error;
+2 -1
fs/xfs/xfs_iops.h
··· 33 33 extern void xfs_setattr_time(struct xfs_inode *ip, struct iattr *iattr); 34 34 extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, 35 35 int flags); 36 - extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap); 36 + extern int xfs_vn_setattr_nonsize(struct dentry *dentry, struct iattr *vap); 37 + extern int xfs_vn_setattr_size(struct dentry *dentry, struct iattr *vap); 37 38 38 39 #endif /* __XFS_IOPS_H__ */