f2fs: use generic checking and prep function for FS_IOC_SETFLAGS

Make the f2fs implementation of FS_IOC_SETFLAGS use the new VFS helper
function vfs_ioc_setflags_prepare().

This is based on a patch from Darrick Wong, but reworked to apply after
commit 360985573b ("f2fs: separate f2fs i_flags from fs_flags and ext4
i_flags").

Originally-from: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Eric Biggers
2019-07-01 13:26:28 -07:00
committed by Jaegeuk Kim
parent 1835402ece
commit f62199a95c
3 changed files with 35 additions and 1 deletions

View File

@@ -1770,7 +1770,8 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
u32 fsflags;
struct f2fs_inode_info *fi = F2FS_I(inode);
u32 fsflags, old_fsflags;
u32 iflags;
int ret;
@@ -1794,8 +1795,14 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
inode_lock(inode);
old_fsflags = f2fs_iflags_to_fsflags(fi->i_flags);
ret = vfs_ioc_setflags_prepare(inode, old_fsflags, fsflags);
if (ret)
goto out;
ret = f2fs_setflags_common(inode, iflags,
f2fs_fsflags_to_iflags(F2FS_SETTABLE_FS_FL));
out:
inode_unlock(inode);
mnt_drop_write_file(filp);
return ret;

View File

@@ -2156,3 +2156,27 @@ struct timespec64 current_time(struct inode *inode)
return timespec64_trunc(now, inode->i_sb->s_time_gran);
}
EXPORT_SYMBOL(current_time);
/*
* Generic function to check FS_IOC_SETFLAGS values and reject any invalid
* configurations.
*
* Note: the caller should be holding i_mutex, or else be sure that they have
* exclusive access to the inode structure.
*/
int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags,
unsigned int flags)
{
/*
* The IMMUTABLE and APPEND_ONLY flags can only be changed by
* the relevant capability.
*
* This test looks nicer. Thanks to Pauline Middelink
*/
if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
!capable(CAP_LINUX_IMMUTABLE))
return -EPERM;
return 0;
}
EXPORT_SYMBOL(vfs_ioc_setflags_prepare);

View File

@@ -3453,4 +3453,7 @@ extern void inode_nohighmem(struct inode *inode);
extern int vfs_fadvise(struct file *file, loff_t offset, loff_t len,
int advice);
int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags,
unsigned int flags);
#endif /* _LINUX_FS_H */