diff options
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r-- | fs/f2fs/file.c | 63 |
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) | |||
1653 | static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) | 1653 | static 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) | |||
1770 | static int f2fs_ioc_setflags(struct file *filp, unsigned long arg) | 1763 | static 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)); |
1798 | out: | ||
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 | ||
2858 | static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg) | 2858 | static 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 | ||
2876 | static int f2fs_ioctl_check_project(struct inode *inode, struct fsxattr *fa) | 2868 | static 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 | ||
2900 | static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg) | 2880 | static 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) |