diff options
| author | Amir Goldstein <amir73il@gmail.com> | 2020-09-29 15:28:48 +0800 | 
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2020-10-06 15:38:15 +0200 | 
| commit | be4df0cea08a8b59eb38d73de988b7ba8022df41 (patch) | |
| tree | 46ca211e654e6bb65b9a8bf7f99c9126fd8ba4f9 | |
| parent | 61536bed2149b082748f8a38c593d915ff3e5957 (diff) | |
ovl: use generic vfs_ioc_setflags_prepare() helper
Canonalize to ioctl FS_* flags instead of inode S_* flags.
Note that we do not call the helper vfs_ioc_fssetxattr_check()
for FS_IOC_FSSETXATTR ioctl. The reason is that underlying filesystem
will perform all the checks. We only need to perform the capability
check before overriding credentials.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
| -rw-r--r-- | fs/overlayfs/file.c | 62 | 
1 files changed, 30 insertions, 32 deletions
| diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 443986ca564b..efccb7c1f9bc 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -559,12 +559,28 @@ static long ovl_real_ioctl(struct file *file, unsigned int cmd,  	return ret;  } +static unsigned int ovl_iflags_to_fsflags(unsigned int iflags) +{ +	unsigned int flags = 0; + +	if (iflags & S_SYNC) +		flags |= FS_SYNC_FL; +	if (iflags & S_APPEND) +		flags |= FS_APPEND_FL; +	if (iflags & S_IMMUTABLE) +		flags |= FS_IMMUTABLE_FL; +	if (iflags & S_NOATIME) +		flags |= FS_NOATIME_FL; + +	return flags; +} +  static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd, -				unsigned long arg, unsigned int iflags) +				unsigned long arg, unsigned int flags)  {  	long ret;  	struct inode *inode = file_inode(file); -	unsigned int old_iflags; +	unsigned int oldflags;  	if (!inode_owner_or_capable(inode))  		return -EACCES; @@ -576,10 +592,9 @@ static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,  	inode_lock(inode);  	/* Check the capability before cred override */ -	ret = -EPERM; -	old_iflags = READ_ONCE(inode->i_flags); -	if (((iflags ^ old_iflags) & (S_APPEND | S_IMMUTABLE)) && -	    !capable(CAP_LINUX_IMMUTABLE)) +	oldflags = ovl_iflags_to_fsflags(READ_ONCE(inode->i_flags)); +	ret = vfs_ioc_setflags_prepare(inode, oldflags, flags); +	if (ret)  		goto unlock;  	ret = ovl_maybe_copy_up(file_dentry(file), O_WRONLY); @@ -598,22 +613,6 @@ unlock:  } -static unsigned int ovl_fsflags_to_iflags(unsigned int flags) -{ -	unsigned int iflags = 0; - -	if (flags & FS_SYNC_FL) -		iflags |= S_SYNC; -	if (flags & FS_APPEND_FL) -		iflags |= S_APPEND; -	if (flags & FS_IMMUTABLE_FL) -		iflags |= S_IMMUTABLE; -	if (flags & FS_NOATIME_FL) -		iflags |= S_NOATIME; - -	return iflags; -} -  static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd,  				  unsigned long arg)  { @@ -622,24 +621,23 @@ static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd,  	if (get_user(flags, (int __user *) arg))  		return -EFAULT; -	return ovl_ioctl_set_flags(file, cmd, arg, -				   ovl_fsflags_to_iflags(flags)); +	return ovl_ioctl_set_flags(file, cmd, arg, flags);  } -static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags) +static unsigned int ovl_fsxflags_to_fsflags(unsigned int xflags)  { -	unsigned int iflags = 0; +	unsigned int flags = 0;  	if (xflags & FS_XFLAG_SYNC) -		iflags |= S_SYNC; +		flags |= FS_SYNC_FL;  	if (xflags & FS_XFLAG_APPEND) -		iflags |= S_APPEND; +		flags |= FS_APPEND_FL;  	if (xflags & FS_XFLAG_IMMUTABLE) -		iflags |= S_IMMUTABLE; +		flags |= FS_IMMUTABLE_FL;  	if (xflags & FS_XFLAG_NOATIME) -		iflags |= S_NOATIME; +		flags |= FS_NOATIME_FL; -	return iflags; +	return flags;  }  static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd, @@ -652,7 +650,7 @@ static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd,  		return -EFAULT;  	return ovl_ioctl_set_flags(file, cmd, arg, -				   ovl_fsxflags_to_iflags(fa.fsx_xflags)); +				   ovl_fsxflags_to_fsflags(fa.fsx_xflags));  }  long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 
