summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r--fs/f2fs/file.c63
1 files changed, 23 insertions, 40 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index f8d46df8fa9e..3e58a6f697dd 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1653,19 +1653,12 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id)
1653static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) 1653static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
1654{ 1654{
1655 struct f2fs_inode_info *fi = F2FS_I(inode); 1655 struct f2fs_inode_info *fi = F2FS_I(inode);
1656 u32 oldflags;
1657 1656
1658 /* Is it quota file? Do not allow user to mess with it */ 1657 /* Is it quota file? Do not allow user to mess with it */
1659 if (IS_NOQUOTA(inode)) 1658 if (IS_NOQUOTA(inode))
1660 return -EPERM; 1659 return -EPERM;
1661 1660
1662 oldflags = fi->i_flags; 1661 fi->i_flags = iflags | (fi->i_flags & ~mask);
1663
1664 if ((iflags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
1665 if (!capable(CAP_LINUX_IMMUTABLE))
1666 return -EPERM;
1667
1668 fi->i_flags = iflags | (oldflags & ~mask);
1669 1662
1670 if (fi->i_flags & F2FS_PROJINHERIT_FL) 1663 if (fi->i_flags & F2FS_PROJINHERIT_FL)
1671 set_inode_flag(inode, FI_PROJ_INHERIT); 1664 set_inode_flag(inode, FI_PROJ_INHERIT);
@@ -1770,7 +1763,8 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
1770static int f2fs_ioc_setflags(struct file *filp, unsigned long arg) 1763static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
1771{ 1764{
1772 struct inode *inode = file_inode(filp); 1765 struct inode *inode = file_inode(filp);
1773 u32 fsflags; 1766 struct f2fs_inode_info *fi = F2FS_I(inode);
1767 u32 fsflags, old_fsflags;
1774 u32 iflags; 1768 u32 iflags;
1775 int ret; 1769 int ret;
1776 1770
@@ -1794,8 +1788,14 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
1794 1788
1795 inode_lock(inode); 1789 inode_lock(inode);
1796 1790
1791 old_fsflags = f2fs_iflags_to_fsflags(fi->i_flags);
1792 ret = vfs_ioc_setflags_prepare(inode, old_fsflags, fsflags);
1793 if (ret)
1794 goto out;
1795
1797 ret = f2fs_setflags_common(inode, iflags, 1796 ret = f2fs_setflags_common(inode, iflags,
1798 f2fs_fsflags_to_iflags(F2FS_SETTABLE_FS_FL)); 1797 f2fs_fsflags_to_iflags(F2FS_SETTABLE_FS_FL));
1798out:
1799 inode_unlock(inode); 1799 inode_unlock(inode);
1800 mnt_drop_write_file(filp); 1800 mnt_drop_write_file(filp);
1801 return ret; 1801 return ret;
@@ -2855,52 +2855,32 @@ static inline u32 f2fs_xflags_to_iflags(u32 xflags)
2855 return iflags; 2855 return iflags;
2856} 2856}
2857 2857
2858static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg) 2858static void f2fs_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
2859{ 2859{
2860 struct inode *inode = file_inode(filp);
2861 struct f2fs_inode_info *fi = F2FS_I(inode); 2860 struct f2fs_inode_info *fi = F2FS_I(inode);
2862 struct fsxattr fa;
2863 2861
2864 memset(&fa, 0, sizeof(struct fsxattr)); 2862 simple_fill_fsxattr(fa, f2fs_iflags_to_xflags(fi->i_flags));
2865 fa.fsx_xflags = f2fs_iflags_to_xflags(fi->i_flags);
2866 2863
2867 if (f2fs_sb_has_project_quota(F2FS_I_SB(inode))) 2864 if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)))
2868 fa.fsx_projid = (__u32)from_kprojid(&init_user_ns, 2865 fa->fsx_projid = from_kprojid(&init_user_ns, fi->i_projid);
2869 fi->i_projid);
2870
2871 if (copy_to_user((struct fsxattr __user *)arg, &fa, sizeof(fa)))
2872 return -EFAULT;
2873 return 0;
2874} 2866}
2875 2867
2876static int f2fs_ioctl_check_project(struct inode *inode, struct fsxattr *fa) 2868static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg)
2877{ 2869{
2878 /* 2870 struct inode *inode = file_inode(filp);
2879 * Project Quota ID state is only allowed to change from within the init 2871 struct fsxattr fa;
2880 * namespace. Enforce that restriction only if we are trying to change
2881 * the quota ID state. Everything else is allowed in user namespaces.
2882 */
2883 if (current_user_ns() == &init_user_ns)
2884 return 0;
2885 2872
2886 if (__kprojid_val(F2FS_I(inode)->i_projid) != fa->fsx_projid) 2873 f2fs_fill_fsxattr(inode, &fa);
2887 return -EINVAL;
2888
2889 if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) {
2890 if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT))
2891 return -EINVAL;
2892 } else {
2893 if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
2894 return -EINVAL;
2895 }
2896 2874
2875 if (copy_to_user((struct fsxattr __user *)arg, &fa, sizeof(fa)))
2876 return -EFAULT;
2897 return 0; 2877 return 0;
2898} 2878}
2899 2879
2900static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg) 2880static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
2901{ 2881{
2902 struct inode *inode = file_inode(filp); 2882 struct inode *inode = file_inode(filp);
2903 struct fsxattr fa; 2883 struct fsxattr fa, old_fa;
2904 u32 iflags; 2884 u32 iflags;
2905 int err; 2885 int err;
2906 2886
@@ -2923,9 +2903,12 @@ static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
2923 return err; 2903 return err;
2924 2904
2925 inode_lock(inode); 2905 inode_lock(inode);
2926 err = f2fs_ioctl_check_project(inode, &fa); 2906
2907 f2fs_fill_fsxattr(inode, &old_fa);
2908 err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa);
2927 if (err) 2909 if (err)
2928 goto out; 2910 goto out;
2911
2929 err = f2fs_setflags_common(inode, iflags, 2912 err = f2fs_setflags_common(inode, iflags,
2930 f2fs_xflags_to_iflags(F2FS_SUPPORTED_XFLAGS)); 2913 f2fs_xflags_to_iflags(F2FS_SUPPORTED_XFLAGS));
2931 if (err) 2914 if (err)