diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-12 16:54:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-12 16:54:37 -0700 |
commit | 5010fe9f095414b959fd6fda63986dc90fd0c419 (patch) | |
tree | 83de620958908e92c567af5fc773768c9f46ada2 /fs/gfs2/file.c | |
parent | 8487d8229990e6eacaf1c854a113c9d16b7b596c (diff) | |
parent | dbc77f31e58b2902a5e7643761c04bf69f57a32a (diff) |
Merge tag 'vfs-fix-ioctl-checking-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull common SETFLAGS/FSSETXATTR parameter checking from Darrick Wong:
"Here's a patch series that sets up common parameter checking functions
for the FS_IOC_SETFLAGS and FS_IOC_FSSETXATTR ioctl implementations.
The goal here is to reduce the amount of behaviorial variance between
the filesystems where those ioctls originated (ext2 and XFS,
respectively) and everybody else.
- Standardize parameter checking for the SETFLAGS and FSSETXATTR
ioctls (which were the file attribute setters for ext4 and xfs and
have now been hoisted to the vfs)
- Only allow the DAX flag to be set on files and directories"
* tag 'vfs-fix-ioctl-checking-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
vfs: only allow FSSETXATTR to set DAX flag on files and dirs
vfs: teach vfs_ioc_fssetxattr_check to check extent size hints
vfs: teach vfs_ioc_fssetxattr_check to check project id info
vfs: create a generic checking function for FS_IOC_FSSETXATTR
vfs: create a generic checking and prep function for FS_IOC_SETFLAGS
Diffstat (limited to 'fs/gfs2/file.c')
-rw-r--r-- | fs/gfs2/file.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 8b0c2bfa90c1..52fa1ef8400b 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -136,27 +136,36 @@ static struct { {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA}, }; +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags) +{ + int i; + u32 fsflags = 0; + + if (S_ISDIR(inode->i_mode)) + gfsflags &= ~GFS2_DIF_JDATA; + else + gfsflags &= ~GFS2_DIF_INHERIT_JDATA; + + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) + if (gfsflags & fsflag_gfs2flag[i].gfsflag) + fsflags |= fsflag_gfs2flag[i].fsflag; + return fsflags; +} + static int gfs2_get_flags(struct file *filp, u32 __user *ptr) { struct inode *inode = file_inode(filp); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; - int i, error; - u32 gfsflags, fsflags = 0; + int error; + u32 fsflags; gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); error = gfs2_glock_nq(&gh); if (error) goto out_uninit; - gfsflags = ip->i_diskflags; - if (S_ISDIR(inode->i_mode)) - gfsflags &= ~GFS2_DIF_JDATA; - else - gfsflags &= ~GFS2_DIF_INHERIT_JDATA; - for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) - if (gfsflags & fsflag_gfs2flag[i].gfsflag) - fsflags |= fsflag_gfs2flag[i].fsflag; + fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags); if (put_user(fsflags, ptr)) error = -EFAULT; @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode) * @filp: file pointer * @reqflags: The flags to set * @mask: Indicates which flags are valid + * @fsflags: The FS_* inode flags passed in * */ -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask, + const u32 fsflags) { struct inode *inode = file_inode(filp); struct gfs2_inode *ip = GFS2_I(inode); @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) struct buffer_head *bh; struct gfs2_holder gh; int error; - u32 new_flags, flags; + u32 new_flags, flags, oldflags; error = mnt_want_write_file(filp); if (error) @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) if (error) goto out_drop_write; + oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags); + error = vfs_ioc_setflags_prepare(inode, oldflags, fsflags); + if (error) + goto out; + error = -EACCES; if (!inode_owner_or_capable(inode)) goto out; @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr) mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA); } - return do_gfs2_set_flags(filp, gfsflags, mask); + return do_gfs2_set_flags(filp, gfsflags, mask, fsflags); } static int gfs2_getlabel(struct file *filp, char __user *label) |