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>
This commit is contained in:
		
							parent
							
								
									073931017b
								
							
						
					
					
						commit
						69bca80744
					
				| @ -973,7 +973,7 @@ xfs_file_fallocate( | ||||
| 
 | ||||
| 		iattr.ia_valid = ATTR_SIZE; | ||||
| 		iattr.ia_size = new_size; | ||||
| 		error = xfs_setattr_size(ip, &iattr); | ||||
| 		error = xfs_vn_setattr_size(file_dentry(file), &iattr); | ||||
| 		if (error) | ||||
| 			goto out_unlock; | ||||
| 	} | ||||
|  | ||||
| @ -1710,7 +1710,7 @@ xfs_inactive_truncate( | ||||
| 	/*
 | ||||
| 	 * Log the inode size first to prevent stale data exposure in the event | ||||
| 	 * of a system crash before the truncate completes. See the related | ||||
| 	 * comment in xfs_setattr_size() for details. | ||||
| 	 * comment in xfs_vn_setattr_size() for details. | ||||
| 	 */ | ||||
| 	ip->i_d.di_size = 0; | ||||
| 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||||
|  | ||||
| @ -720,7 +720,7 @@ xfs_ioc_space( | ||||
| 		iattr.ia_valid = ATTR_SIZE; | ||||
| 		iattr.ia_size = bf->l_start; | ||||
| 
 | ||||
| 		error = xfs_setattr_size(ip, &iattr); | ||||
| 		error = xfs_vn_setattr_size(file_dentry(filp), &iattr); | ||||
| 		break; | ||||
| 	default: | ||||
| 		ASSERT(0); | ||||
|  | ||||
| @ -542,6 +542,30 @@ xfs_setattr_time( | ||||
| 		inode->i_mtime = iattr->ia_mtime; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| xfs_vn_change_ok( | ||||
| 	struct dentry	*dentry, | ||||
| 	struct iattr	*iattr) | ||||
| { | ||||
| 	struct inode		*inode = d_inode(dentry); | ||||
| 	struct xfs_inode	*ip = XFS_I(inode); | ||||
| 	struct xfs_mount	*mp = ip->i_mount; | ||||
| 
 | ||||
| 	if (mp->m_flags & XFS_MOUNT_RDONLY) | ||||
| 		return -EROFS; | ||||
| 
 | ||||
| 	if (XFS_FORCED_SHUTDOWN(mp)) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	return inode_change_ok(inode, iattr); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set non-size attributes of an inode. | ||||
|  * | ||||
|  * Caution: The caller of this function is responsible for calling | ||||
|  * inode_change_ok() or otherwise verifying the change is fine. | ||||
|  */ | ||||
| int | ||||
| xfs_setattr_nonsize( | ||||
| 	struct xfs_inode	*ip, | ||||
| @ -558,21 +582,6 @@ xfs_setattr_nonsize( | ||||
| 	struct xfs_dquot	*udqp = NULL, *gdqp = NULL; | ||||
| 	struct xfs_dquot	*olddquot1 = NULL, *olddquot2 = NULL; | ||||
| 
 | ||||
| 	trace_xfs_setattr(ip); | ||||
| 
 | ||||
| 	/* If acls are being inherited, we already have this checked */ | ||||
| 	if (!(flags & XFS_ATTR_NOACL)) { | ||||
| 		if (mp->m_flags & XFS_MOUNT_RDONLY) | ||||
| 			return -EROFS; | ||||
| 
 | ||||
| 		if (XFS_FORCED_SHUTDOWN(mp)) | ||||
| 			return -EIO; | ||||
| 
 | ||||
| 		error = inode_change_ok(inode, iattr); | ||||
| 		if (error) | ||||
| 			return error; | ||||
| 	} | ||||
| 
 | ||||
| 	ASSERT((mask & ATTR_SIZE) == 0); | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -743,8 +752,27 @@ out_dqrele: | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| xfs_vn_setattr_nonsize( | ||||
| 	struct dentry		*dentry, | ||||
| 	struct iattr		*iattr) | ||||
| { | ||||
| 	struct xfs_inode	*ip = XFS_I(d_inode(dentry)); | ||||
| 	int error; | ||||
| 
 | ||||
| 	trace_xfs_setattr(ip); | ||||
| 
 | ||||
| 	error = xfs_vn_change_ok(dentry, iattr); | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 	return xfs_setattr_nonsize(ip, iattr, 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Truncate file.  Must have write permission and not be a directory. | ||||
|  * | ||||
|  * Caution: The caller of this function is responsible for calling | ||||
|  * inode_change_ok() or otherwise verifying the change is fine. | ||||
|  */ | ||||
| int | ||||
| xfs_setattr_size( | ||||
| @ -759,18 +787,6 @@ xfs_setattr_size( | ||||
| 	uint			lock_flags = 0; | ||||
| 	bool			did_zeroing = false; | ||||
| 
 | ||||
| 	trace_xfs_setattr(ip); | ||||
| 
 | ||||
| 	if (mp->m_flags & XFS_MOUNT_RDONLY) | ||||
| 		return -EROFS; | ||||
| 
 | ||||
| 	if (XFS_FORCED_SHUTDOWN(mp)) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	error = inode_change_ok(inode, iattr); | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 
 | ||||
| 	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | ||||
| 	ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); | ||||
| 	ASSERT(S_ISREG(inode->i_mode)); | ||||
| @ -942,16 +958,32 @@ out_trans_cancel: | ||||
| 	goto out_unlock; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| xfs_vn_setattr_size( | ||||
| 	struct dentry		*dentry, | ||||
| 	struct iattr		*iattr) | ||||
| { | ||||
| 	struct xfs_inode	*ip = XFS_I(d_inode(dentry)); | ||||
| 	int error; | ||||
| 
 | ||||
| 	trace_xfs_setattr(ip); | ||||
| 
 | ||||
| 	error = xfs_vn_change_ok(dentry, iattr); | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 	return xfs_setattr_size(ip, iattr); | ||||
| } | ||||
| 
 | ||||
| STATIC int | ||||
| xfs_vn_setattr( | ||||
| 	struct dentry		*dentry, | ||||
| 	struct iattr		*iattr) | ||||
| { | ||||
| 	struct xfs_inode	*ip = XFS_I(d_inode(dentry)); | ||||
| 	int			error; | ||||
| 
 | ||||
| 	if (iattr->ia_valid & ATTR_SIZE) { | ||||
| 		uint		iolock = XFS_IOLOCK_EXCL; | ||||
| 		struct xfs_inode	*ip = XFS_I(d_inode(dentry)); | ||||
| 		uint			iolock = XFS_IOLOCK_EXCL; | ||||
| 
 | ||||
| 		xfs_ilock(ip, iolock); | ||||
| 		error = xfs_break_layouts(d_inode(dentry), &iolock, true); | ||||
| @ -959,11 +991,11 @@ xfs_vn_setattr( | ||||
| 			xfs_ilock(ip, XFS_MMAPLOCK_EXCL); | ||||
| 			iolock |= XFS_MMAPLOCK_EXCL; | ||||
| 
 | ||||
| 			error = xfs_setattr_size(ip, iattr); | ||||
| 			error = xfs_vn_setattr_size(dentry, iattr); | ||||
| 		} | ||||
| 		xfs_iunlock(ip, iolock); | ||||
| 	} else { | ||||
| 		error = xfs_setattr_nonsize(ip, iattr, 0); | ||||
| 		error = xfs_vn_setattr_nonsize(dentry, iattr); | ||||
| 	} | ||||
| 
 | ||||
| 	return error; | ||||
|  | ||||
| @ -33,6 +33,7 @@ extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); | ||||
| extern void xfs_setattr_time(struct xfs_inode *ip, struct iattr *iattr); | ||||
| extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, | ||||
| 			       int flags); | ||||
| extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap); | ||||
| extern int xfs_vn_setattr_nonsize(struct dentry *dentry, struct iattr *vap); | ||||
| extern int xfs_vn_setattr_size(struct dentry *dentry, struct iattr *vap); | ||||
| 
 | ||||
| #endif /* __XFS_IOPS_H__ */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user