cmnt: [X] [PATCH] fixes for LP: #1415636/CVE-2015-1350

Khaled Elmously khalid.elmously at canonical.com
Thu Aug 2 05:44:30 UTC 2018


On 2018-08-01 14:58:59 , José Pekkarinen wrote:
> fs: Avoid premature clearing of capabilities(030b533c4fd)
> Reviewed-by: Christoph Hellwig <hch at lst.de>
> by: Jan Kara <jack at suse.cz>
> 
> It's applied on:
> 
> UBUNTU: Ubuntu-lts-3.19.0-82.90~14.04.1(ceea1114793f68).
> Signed-off-by: Brad Figg <brad.figg at canonical.com>
> 
> Currently, notify_change() clears capabilities or IMA attributes by
> calling security_inode_killpriv() before calling into ->setattr. Thus it
> happens before any other permission checks in inode_change_ok() and user
> is thus allowed to trigger clearing of capabilities or IMA attributes
> for any file he can look up e.g. by calling chown for that file. This is
> unexpected and can lead to user DoSing a system.
> 
> Fix the problem by calling security_inode_killpriv() at the end of
> inode_change_ok() instead of from notify_change(). At that moment we are
> sure user has permissions to do the requested change.
> 
> References: CVE-2015-1350
> Signed-off-by: José Pekkarinen <jose.pekkarinen at canonical.com>
> ---
>  fs/9p/vfs_inode.c       |  2 +-
>  fs/9p/vfs_inode_dotl.c  |  2 +-
>  fs/adfs/inode.c         |  2 +-
>  fs/affs/inode.c         |  2 +-
>  fs/attr.c               | 23 ++++++++++++++++-------
>  fs/btrfs/inode.c        |  2 +-
>  fs/ceph/inode.c         |  2 +-
>  fs/cifs/inode.c         |  4 ++--
>  fs/ecryptfs/inode.c     |  2 +-
>  fs/exofs/inode.c        |  2 +-
>  fs/ext2/inode.c         |  2 +-
>  fs/ext3/inode.c         |  2 +-
>  fs/ext4/inode.c         |  2 +-
>  fs/f2fs/file.c          |  2 +-
>  fs/fat/file.c           |  2 +-
>  fs/fuse/dir.c           | 13 +++++++------
>  fs/fuse/file.c          |  3 ++-
>  fs/fuse/fuse_i.h        |  2 +-
>  fs/gfs2/inode.c         |  2 +-
>  fs/hfs/inode.c          |  2 +-
>  fs/hfsplus/inode.c      |  2 +-
>  fs/hostfs/hostfs_kern.c |  2 +-
>  fs/hpfs/inode.c         |  2 +-
>  fs/hugetlbfs/inode.c    |  2 +-
>  fs/jffs2/fs.c           |  2 +-
>  fs/jfs/file.c           |  2 +-
>  fs/kernfs/inode.c       |  2 +-
>  fs/libfs.c              |  2 +-
>  fs/logfs/file.c         |  2 +-
>  fs/minix/file.c         |  2 +-
>  fs/ncpfs/inode.c        |  2 +-
>  fs/nfsd/vfs.c           |  7 ++++---
>  fs/nilfs2/inode.c       |  2 +-
>  fs/ntfs/inode.c         |  2 +-
>  fs/ocfs2/dlmfs/dlmfs.c  |  2 +-
>  fs/ocfs2/file.c         |  2 +-
>  fs/omfs/file.c          |  2 +-
>  fs/proc/base.c          |  2 +-
>  fs/proc/generic.c       |  2 +-
>  fs/proc/proc_sysctl.c   |  2 +-
>  fs/ramfs/file-nommu.c   |  2 +-
>  fs/reiserfs/inode.c     |  2 +-
>  fs/sysv/file.c          |  2 +-
>  fs/ubifs/file.c         |  2 +-
>  fs/udf/file.c           |  2 +-
>  fs/ufs/truncate.c       |  2 +-
>  fs/xfs/xfs_iops.c       |  6 ++++--
>  include/linux/fs.h      |  2 +-
>  mm/shmem.c              |  2 +-
>  49 files changed, 78 insertions(+), 64 deletions(-)
> 
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 711d744..65fcb86 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -1094,7 +1094,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
>  	struct p9_wstat wstat;
>  
>  	p9_debug(P9_DEBUG_VFS, "\n");
> -	retval = inode_change_ok(dentry->d_inode, iattr);
> +	retval = inode_change_ok(dentry, iattr);
>  	if (retval)
>  		return retval;
>  
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index 1254c7b..961a5b7 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -560,7 +560,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
>  
>  	p9_debug(P9_DEBUG_VFS, "\n");
>  
> -	retval = inode_change_ok(inode, iattr);
> +	retval = inode_change_ok(dentry, iattr);
>  	if (retval)
>  		return retval;
>  
> diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
> index b9acada..fceb187 100644
> --- a/fs/adfs/inode.c
> +++ b/fs/adfs/inode.c
> @@ -303,7 +303,7 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
>  	unsigned int ia_valid = attr->ia_valid;
>  	int error;
>  	
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  
>  	/*
>  	 * we can't change the UID or GID of any file -
> diff --git a/fs/affs/inode.c b/fs/affs/inode.c
> index d0609a2..e929583 100644
> --- a/fs/affs/inode.c
> +++ b/fs/affs/inode.c
> @@ -219,7 +219,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
>  
>  	pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
>  
> -	error = inode_change_ok(inode,attr);
> +	error = inode_change_ok(dentry,attr);
>  	if (error)
>  		goto out;
>  
> diff --git a/fs/attr.c b/fs/attr.c
> index 6530ced..72ec99f 100644
> --- a/fs/attr.c
> +++ b/fs/attr.c
> @@ -28,8 +28,9 @@
>   * Should be called as the first thing in ->setattr implementations,
>   * possibly after taking additional locks.
>   */
> -int inode_change_ok(const struct inode *inode, struct iattr *attr)
> +int inode_change_ok(struct dentry *dentry, struct iattr *attr)
>  {
> +	struct inode *inode = d_inode(dentry);
>  	unsigned int ia_valid = attr->ia_valid;
>  
>  	/*
> @@ -44,7 +45,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>  
>  	/* If force is set do it anyway. */
>  	if (ia_valid & ATTR_FORCE)
> -		return 0;
> +		goto kill_priv;
>  
>  	/* Make sure a caller can chown. */
>  	if ((ia_valid & ATTR_UID) &&
> @@ -77,6 +78,16 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>  			return -EPERM;
>  	}
>  
> +kill_priv:
> +	/* User has permission for the change */
> +	if (ia_valid & ATTR_KILL_PRIV) {
> +		int error;
> +
> +		error = security_inode_killpriv(dentry);
> +		if (error)
> +			return error;
> +	}
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL(inode_change_ok);
> @@ -217,13 +228,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
>  	if (!(ia_valid & ATTR_MTIME_SET))
>  		attr->ia_mtime = now;
>  	if (ia_valid & ATTR_KILL_PRIV) {
> -		attr->ia_valid &= ~ATTR_KILL_PRIV;
> -		ia_valid &= ~ATTR_KILL_PRIV;
>  		error = security_inode_need_killpriv(dentry);
> -		if (error > 0)
> -			error = security_inode_killpriv(dentry);
> -		if (error)
> +		if (error < 0)
>  			return error;
> +		if (error == 0)
> +			ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
>  	}
>  
>  	/*
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 508a4ca..47d3999 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -4805,7 +4805,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
>  	if (btrfs_root_readonly(root))
>  		return -EROFS;
>  
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		return err;
>  
> diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
> index f61a741..4003158 100644
> --- a/fs/ceph/inode.c
> +++ b/fs/ceph/inode.c
> @@ -1727,7 +1727,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
>  	if (ceph_snap(inode) != CEPH_NOSNAP)
>  		return -EROFS;
>  
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err != 0)
>  		return err;
>  
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index 5772aa0..0e0766c 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -2092,7 +2092,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
>  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
>  		attrs->ia_valid |= ATTR_FORCE;
>  
> -	rc = inode_change_ok(inode, attrs);
> +	rc = inode_change_ok(direntry, attrs);
>  	if (rc < 0)
>  		goto out;
>  
> @@ -2233,7 +2233,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
>  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
>  		attrs->ia_valid |= ATTR_FORCE;
>  
> -	rc = inode_change_ok(inode, attrs);
> +	rc = inode_change_ok(direntry, attrs);
>  	if (rc < 0) {
>  		free_xid(xid);
>  		return rc;
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index 1686dc2..3cf2cdd 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -943,7 +943,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
>  	}
>  	mutex_unlock(&crypt_stat->cs_mutex);
>  
> -	rc = inode_change_ok(inode, ia);
> +	rc = inode_change_ok(dentry, ia);
>  	if (rc)
>  		goto out;
>  	if (ia->ia_valid & ATTR_SIZE) {
> diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
> index f1d3d4e..4bb7077 100644
> --- a/fs/exofs/inode.c
> +++ b/fs/exofs/inode.c
> @@ -1039,7 +1039,7 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
>  	if (unlikely(error))
>  		return error;
>  
> -	error = inode_change_ok(inode, iattr);
> +	error = inode_change_ok(dentry, iattr);
>  	if (unlikely(error))
>  		return error;
>  
> diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
> index 36d35c3..c75bbd4 100644
> --- a/fs/ext2/inode.c
> +++ b/fs/ext2/inode.c
> @@ -1547,7 +1547,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, iattr);
> +	error = inode_change_ok(dentry, iattr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
> index 2c6ccc4..421b537 100644
> --- a/fs/ext3/inode.c
> +++ b/fs/ext3/inode.c
> @@ -3244,7 +3244,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
>  	int error, rc = 0;
>  	const unsigned int ia_valid = attr->ia_valid;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 77c8ce1..51ea725 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -4482,7 +4482,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
>  	int orphan = 0;
>  	const unsigned int ia_valid = attr->ia_valid;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 3c27e0e..1ca06de 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -600,7 +600,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct f2fs_inode_info *fi = F2FS_I(inode);
>  	int err;
>  
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		return err;
>  
> diff --git a/fs/fat/file.c b/fs/fat/file.c
> index 8429c68..626f9d4 100644
> --- a/fs/fat/file.c
> +++ b/fs/fat/file.c
> @@ -394,7 +394,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
>  			attr->ia_valid &= ~TIMES_SET_FLAGS;
>  	}
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	attr->ia_valid = ia_valid;
>  	if (error) {
>  		if (sbi->options.quiet)
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index 08e7b1a..7b2a04c 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -1602,9 +1602,10 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
>   * vmtruncate() doesn't allow for this case, so do the rlimit checking
>   * and the actual truncation by hand.
>   */
> -int fuse_do_setattr(struct inode *inode, struct iattr *attr,
> +int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
>  		    struct file *file)
>  {
> +	struct inode *inode = d_inode(dentry);
>  	struct fuse_conn *fc = get_fuse_conn(inode);
>  	struct fuse_inode *fi = get_fuse_inode(inode);
>  	FUSE_ARGS(args);
> @@ -1619,7 +1620,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
>  	if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
>  		attr->ia_valid |= ATTR_FORCE;
>  
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		return err;
>  
> @@ -1710,17 +1711,17 @@ error:
>  	return err;
>  }
>  
> -static int fuse_setattr(struct dentry *entry, struct iattr *attr)
> +static int fuse_setattr(struct dentry *dentry, struct iattr *attr)
>  {
> -	struct inode *inode = entry->d_inode;
> +	struct inode *inode = dentry->d_inode;
>  
>  	if (!fuse_allow_current_process(get_fuse_conn(inode)))
>  		return -EACCES;
>  
>  	if (attr->ia_valid & ATTR_FILE)
> -		return fuse_do_setattr(inode, attr, attr->ia_file);
> +		return fuse_do_setattr(dentry, attr, attr->ia_file);
>  	else
> -		return fuse_do_setattr(inode, attr, NULL);
> +		return fuse_do_setattr(dentry, attr, NULL);
>  }
>  
>  static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 60788e9..dbcc12a 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -2782,6 +2782,7 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc,
>  static void fuse_do_truncate(struct file *file)
>  {
>  	struct inode *inode = file->f_mapping->host;
> +	struct dentry *dentry = inode->i_sb->s_root;
>  	struct iattr attr;
>  
>  	attr.ia_valid = ATTR_SIZE;
> @@ -2790,7 +2791,7 @@ static void fuse_do_truncate(struct file *file)
>  	attr.ia_file = file;
>  	attr.ia_valid |= ATTR_FILE;
>  
> -	fuse_do_setattr(inode, &attr, file);
> +	fuse_do_setattr(dentry, &attr, file);
>  }
>  
>  static inline loff_t fuse_round_up(loff_t off)
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 1cdfb07..195c942 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -903,7 +903,7 @@ bool fuse_write_update_size(struct inode *inode, loff_t pos);
>  int fuse_flush_times(struct inode *inode, struct fuse_file *ff);
>  int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
>  
> -int fuse_do_setattr(struct inode *inode, struct iattr *attr,
> +int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
>  		    struct file *file);
>  
>  void fuse_set_initialized(struct fuse_conn *fc);
> diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> index 9054002..c7fb53e 100644
> --- a/fs/gfs2/inode.c
> +++ b/fs/gfs2/inode.c
> @@ -1760,7 +1760,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
>  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
>  		goto out;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		goto out;
>  
> diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
> index d0929bc..9b42ee0 100644
> --- a/fs/hfs/inode.c
> +++ b/fs/hfs/inode.c
> @@ -604,7 +604,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
>  	struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
>  	int error;
>  
> -	error = inode_change_ok(inode, attr); /* basic permission checks */
> +	error = inode_change_ok(dentry, attr); /* basic permission checks */
>  	if (error)
>  		return error;
>  
> diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
> index 0cf786f..a74ff43 100644
> --- a/fs/hfsplus/inode.c
> +++ b/fs/hfsplus/inode.c
> @@ -247,7 +247,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
> index 75967b7e..bbf633f 100644
> --- a/fs/hostfs/hostfs_kern.c
> +++ b/fs/hostfs/hostfs_kern.c
> @@ -802,7 +802,7 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
>  
>  	int fd = HOSTFS_I(inode)->fd;
>  
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		return err;
>  
> diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
> index 7ce4b74..8e6942e 100644
> --- a/fs/hpfs/inode.c
> +++ b/fs/hpfs/inode.c
> @@ -272,7 +272,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
>  	if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
>  		goto out_unlock;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		goto out_unlock;
>  
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 5eba47f..a4ddc94 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -429,7 +429,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
>  
>  	BUG_ON(!inode);
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
> index 601afd1..870ed4f 100644
> --- a/fs/jffs2/fs.c
> +++ b/fs/jffs2/fs.c
> @@ -193,7 +193,7 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
>  	struct inode *inode = dentry->d_inode;
>  	int rc;
>  
> -	rc = inode_change_ok(inode, iattr);
> +	rc = inode_change_ok(dentry, iattr);
>  	if (rc)
>  		return rc;
>  
> diff --git a/fs/jfs/file.c b/fs/jfs/file.c
> index 33aa0cc..2ede547 100644
> --- a/fs/jfs/file.c
> +++ b/fs/jfs/file.c
> @@ -103,7 +103,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
>  	struct inode *inode = dentry->d_inode;
>  	int rc;
>  
> -	rc = inode_change_ok(inode, iattr);
> +	rc = inode_change_ok(dentry, iattr);
>  	if (rc)
>  		return rc;
>  
> diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
> index 5b8ab29..325234f 100644
> --- a/fs/kernfs/inode.c
> +++ b/fs/kernfs/inode.c
> @@ -131,7 +131,7 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
>  		return -EINVAL;
>  
>  	mutex_lock(&kernfs_mutex);
> -	error = inode_change_ok(inode, iattr);
> +	error = inode_change_ok(dentry, iattr);
>  	if (error)
>  		goto out;
>  
> diff --git a/fs/libfs.c b/fs/libfs.c
> index 3a5deb3..5509af4 100644
> --- a/fs/libfs.c
> +++ b/fs/libfs.c
> @@ -371,7 +371,7 @@ int simple_setattr(struct dentry *dentry, struct iattr *iattr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, iattr);
> +	error = inode_change_ok(dentry, iattr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/logfs/file.c b/fs/logfs/file.c
> index 8538752..bf8b09d 100644
> --- a/fs/logfs/file.c
> +++ b/fs/logfs/file.c
> @@ -244,7 +244,7 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  	int err = 0;
>  
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		return err;
>  
> diff --git a/fs/minix/file.c b/fs/minix/file.c
> index a967de0..57bd2a4 100644
> --- a/fs/minix/file.c
> +++ b/fs/minix/file.c
> @@ -28,7 +28,7 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
> index e31e589..35a6d37 100644
> --- a/fs/ncpfs/inode.c
> +++ b/fs/ncpfs/inode.c
> @@ -885,7 +885,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
>  	/* ageing the dentry to force validation */
>  	ncp_age_dentry(server, dentry);
>  
> -	result = inode_change_ok(inode, attr);
> +	result = inode_change_ok(dentry, attr);
>  	if (result < 0)
>  		goto out;
>  
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 5685c67..38e5b6a 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -300,7 +300,7 @@ commit_metadata(struct svc_fh *fhp)
>   * NFS semantics and what Linux expects.
>   */
>  static void
> -nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
> +nfsd_sanitize_attrs(struct dentry *dentry, struct iattr *iap)
>  {
>  	/*
>  	 * NFSv2 does not differentiate between "set-[ac]time-to-now"
> @@ -313,6 +313,7 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
>  	 * We only call inode_change_ok as the last test as technically
>  	 * it is not an interface that we should be using.
>  	 */
> +	struct inode *inode = d_inode(dentry);
>  #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
>  #define	MAX_TOUCH_TIME_ERROR (30*60)
>  	if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET &&
> @@ -328,7 +329,7 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
>  		if (delta < 0)
>  			delta = -delta;
>  		if (delta < MAX_TOUCH_TIME_ERROR &&
> -		    inode_change_ok(inode, iap) != 0) {
> +		    inode_change_ok(dentry, iap) != 0) {
>  			/*
>  			 * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
>  			 * This will cause notify_change to set these times
> @@ -435,7 +436,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
>  	if (!iap->ia_valid)
>  		goto out;
>  
> -	nfsd_sanitize_attrs(inode, iap);
> +	nfsd_sanitize_attrs(dentry, iap);
>  
>  	/*
>  	 * The size case is special, it changes the file in addition to the
> diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
> index 8b59695..0791dd4 100644
> --- a/fs/nilfs2/inode.c
> +++ b/fs/nilfs2/inode.c
> @@ -840,7 +840,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
>  	struct super_block *sb = inode->i_sb;
>  	int err;
>  
> -	err = inode_change_ok(inode, iattr);
> +	err = inode_change_ok(dentry, iattr);
>  	if (err)
>  		return err;
>  
> diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
> index 898b994..6d51746 100644
> --- a/fs/ntfs/inode.c
> +++ b/fs/ntfs/inode.c
> @@ -2894,7 +2894,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
>  	int err;
>  	unsigned int ia_valid = attr->ia_valid;
>  
> -	err = inode_change_ok(vi, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		goto out;
>  	/* We do not support NTFS ACLs yet. */
> diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
> index 57c40e3..4473e95 100644
> --- a/fs/ocfs2/dlmfs/dlmfs.c
> +++ b/fs/ocfs2/dlmfs/dlmfs.c
> @@ -211,7 +211,7 @@ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  
>  	attr->ia_valid &= ~ATTR_SIZE;
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
> index 7e5aa39..9067886 100644
> --- a/fs/ocfs2/file.c
> +++ b/fs/ocfs2/file.c
> @@ -1143,7 +1143,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
>  	if (!(attr->ia_valid & OCFS2_VALID_ATTRS))
>  		return 0;
>  
> -	status = inode_change_ok(inode, attr);
> +	status = inode_change_ok(dentry, attr);
>  	if (status)
>  		return status;
>  
> diff --git a/fs/omfs/file.c b/fs/omfs/file.c
> index 902e885..db6314c 100644
> --- a/fs/omfs/file.c
> +++ b/fs/omfs/file.c
> @@ -351,7 +351,7 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index d022159..7abfc57 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -509,7 +509,7 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
>  	if (attr->ia_valid & ATTR_MODE)
>  		return -EPERM;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/proc/generic.c b/fs/proc/generic.c
> index aaabab4..5f24651 100644
> --- a/fs/proc/generic.c
> +++ b/fs/proc/generic.c
> @@ -105,7 +105,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
>  	struct proc_dir_entry *de = PDE(inode);
>  	int error;
>  
> -	error = inode_change_ok(inode, iattr);
> +	error = inode_change_ok(dentry, iattr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index 3f7dc3e..be5b366 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -753,7 +753,7 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
>  	if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
>  		return -EPERM;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
> index bbafbde..daba062 100644
> --- a/fs/ramfs/file-nommu.c
> +++ b/fs/ramfs/file-nommu.c
> @@ -163,7 +163,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
>  	int ret = 0;
>  
>  	/* POSIX UID/GID verification for setting inode attributes */
> -	ret = inode_change_ok(inode, ia);
> +	ret = inode_change_ok(dentry, ia);
>  	if (ret)
>  		return ret;
>  
> diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
> index a7eec98..80f5192 100644
> --- a/fs/reiserfs/inode.c
> +++ b/fs/reiserfs/inode.c
> @@ -3312,7 +3312,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
>  	unsigned int ia_valid;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/sysv/file.c b/fs/sysv/file.c
> index b00811c..09099b5 100644
> --- a/fs/sysv/file.c
> +++ b/fs/sysv/file.c
> @@ -35,7 +35,7 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
> index 538519e..b663d11 100644
> --- a/fs/ubifs/file.c
> +++ b/fs/ubifs/file.c
> @@ -1262,7 +1262,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
>  
>  	dbg_gen("ino %lu, mode %#x, ia_valid %#x",
>  		inode->i_ino, inode->i_mode, attr->ia_valid);
> -	err = inode_change_ok(inode, attr);
> +	err = inode_change_ok(dentry, attr);
>  	if (err)
>  		return err;
>  
> diff --git a/fs/udf/file.c b/fs/udf/file.c
> index 08f3555..e2a382e 100644
> --- a/fs/udf/file.c
> +++ b/fs/udf/file.c
> @@ -258,7 +258,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
> index f04f89f..926ba19 100644
> --- a/fs/ufs/truncate.c
> +++ b/fs/ufs/truncate.c
> @@ -496,7 +496,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
>  	unsigned int ia_valid = attr->ia_valid;
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 17d057c..ea6af4f 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -530,6 +530,7 @@ xfs_setattr_nonsize(
>  {
>  	xfs_mount_t		*mp = ip->i_mount;
>  	struct inode		*inode = VFS_I(ip);
> +	struct dentry 		*dentry = inode->i_sb->s_root;

I'm not sure I understand the above line. Can you please explain why it's true?



>  	int			mask = iattr->ia_valid;
>  	xfs_trans_t		*tp;
>  	int			error;
> @@ -548,7 +549,7 @@ xfs_setattr_nonsize(
>  		if (XFS_FORCED_SHUTDOWN(mp))
>  			return -EIO;
>  
> -		error = inode_change_ok(inode, iattr);
> +		error = inode_change_ok(dentry, iattr);
>  		if (error)
>  			return error;
>  	}
> @@ -736,6 +737,7 @@ xfs_setattr_size(
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
>  	struct inode		*inode = VFS_I(ip);
> +	struct dentry		*dentry = inode->i_sb->s_root;

Same for the preceding line.


>  	xfs_off_t		oldsize, newsize;
>  	struct xfs_trans	*tp;
>  	int			error;
> @@ -751,7 +753,7 @@ xfs_setattr_size(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	error = inode_change_ok(inode, iattr);
> +	error = inode_change_ok(dentry, iattr);
>  	if (error)
>  		return error;
>  
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 92c88b8..d12c959 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -2690,7 +2690,7 @@ extern int buffer_migrate_page(struct address_space *,
>  #define buffer_migrate_page NULL
>  #endif
>  
> -extern int inode_change_ok(const struct inode *, struct iattr *);
> +extern int inode_change_ok(struct dentry *, struct iattr *);
>  extern int inode_newsize_ok(const struct inode *, loff_t offset);
>  extern void setattr_copy(struct inode *inode, const struct iattr *attr);
>  
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 993e6ba..fc6cab1 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -553,7 +553,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
>  	struct shmem_inode_info *info = SHMEM_I(inode);
>  	int error;
>  
> -	error = inode_change_ok(inode, attr);
> +	error = inode_change_ok(dentry, attr);
>  	if (error)
>  		return error;
>  
> -- 
> 2.7.4
> 
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team




More information about the kernel-team mailing list