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
This commit is contained in:
@@ -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)
|
||||
|
Reference in New Issue
Block a user