|
20 | 20 | #include <linux/uaccess.h> |
21 | 21 | #include <linux/delay.h> |
22 | 22 | #include <linux/iversion.h> |
| 23 | +#include <linux/fileattr.h> |
23 | 24 | #include "ext4_jbd2.h" |
24 | 25 | #include "ext4.h" |
25 | 26 | #include <linux/fsmap.h> |
@@ -344,11 +345,6 @@ static int ext4_ioctl_setflags(struct inode *inode, |
344 | 345 | goto flags_out; |
345 | 346 |
|
346 | 347 | oldflags = ei->i_flags; |
347 | | - |
348 | | - err = vfs_ioc_setflags_prepare(inode, oldflags, flags); |
349 | | - if (err) |
350 | | - goto flags_out; |
351 | | - |
352 | 348 | /* |
353 | 349 | * The JOURNAL_DATA flag can only be changed by |
354 | 350 | * the relevant capability. |
@@ -459,9 +455,8 @@ static int ext4_ioctl_setflags(struct inode *inode, |
459 | 455 | } |
460 | 456 |
|
461 | 457 | #ifdef CONFIG_QUOTA |
462 | | -static int ext4_ioctl_setproject(struct file *filp, __u32 projid) |
| 458 | +static int ext4_ioctl_setproject(struct inode *inode, __u32 projid) |
463 | 459 | { |
464 | | - struct inode *inode = file_inode(filp); |
465 | 460 | struct super_block *sb = inode->i_sb; |
466 | 461 | struct ext4_inode_info *ei = EXT4_I(inode); |
467 | 462 | int err, rc; |
@@ -545,64 +540,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) |
545 | 540 | return err; |
546 | 541 | } |
547 | 542 | #else |
548 | | -static int ext4_ioctl_setproject(struct file *filp, __u32 projid) |
| 543 | +static int ext4_ioctl_setproject(struct inode *inode, __u32 projid) |
549 | 544 | { |
550 | 545 | if (projid != EXT4_DEF_PROJID) |
551 | 546 | return -EOPNOTSUPP; |
552 | 547 | return 0; |
553 | 548 | } |
554 | 549 | #endif |
555 | 550 |
|
556 | | -/* Transfer internal flags to xflags */ |
557 | | -static inline __u32 ext4_iflags_to_xflags(unsigned long iflags) |
558 | | -{ |
559 | | - __u32 xflags = 0; |
560 | | - |
561 | | - if (iflags & EXT4_SYNC_FL) |
562 | | - xflags |= FS_XFLAG_SYNC; |
563 | | - if (iflags & EXT4_IMMUTABLE_FL) |
564 | | - xflags |= FS_XFLAG_IMMUTABLE; |
565 | | - if (iflags & EXT4_APPEND_FL) |
566 | | - xflags |= FS_XFLAG_APPEND; |
567 | | - if (iflags & EXT4_NODUMP_FL) |
568 | | - xflags |= FS_XFLAG_NODUMP; |
569 | | - if (iflags & EXT4_NOATIME_FL) |
570 | | - xflags |= FS_XFLAG_NOATIME; |
571 | | - if (iflags & EXT4_PROJINHERIT_FL) |
572 | | - xflags |= FS_XFLAG_PROJINHERIT; |
573 | | - if (iflags & EXT4_DAX_FL) |
574 | | - xflags |= FS_XFLAG_DAX; |
575 | | - return xflags; |
576 | | -} |
577 | | - |
578 | | -#define EXT4_SUPPORTED_FS_XFLAGS (FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | \ |
579 | | - FS_XFLAG_APPEND | FS_XFLAG_NODUMP | \ |
580 | | - FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT | \ |
581 | | - FS_XFLAG_DAX) |
582 | | - |
583 | | -/* Transfer xflags flags to internal */ |
584 | | -static inline unsigned long ext4_xflags_to_iflags(__u32 xflags) |
585 | | -{ |
586 | | - unsigned long iflags = 0; |
587 | | - |
588 | | - if (xflags & FS_XFLAG_SYNC) |
589 | | - iflags |= EXT4_SYNC_FL; |
590 | | - if (xflags & FS_XFLAG_IMMUTABLE) |
591 | | - iflags |= EXT4_IMMUTABLE_FL; |
592 | | - if (xflags & FS_XFLAG_APPEND) |
593 | | - iflags |= EXT4_APPEND_FL; |
594 | | - if (xflags & FS_XFLAG_NODUMP) |
595 | | - iflags |= EXT4_NODUMP_FL; |
596 | | - if (xflags & FS_XFLAG_NOATIME) |
597 | | - iflags |= EXT4_NOATIME_FL; |
598 | | - if (xflags & FS_XFLAG_PROJINHERIT) |
599 | | - iflags |= EXT4_PROJINHERIT_FL; |
600 | | - if (xflags & FS_XFLAG_DAX) |
601 | | - iflags |= EXT4_DAX_FL; |
602 | | - |
603 | | - return iflags; |
604 | | -} |
605 | | - |
606 | 551 | static int ext4_shutdown(struct super_block *sb, unsigned long arg) |
607 | 552 | { |
608 | 553 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
@@ -770,15 +715,52 @@ static long ext4_ioctl_group_add(struct file *file, |
770 | 715 | return err; |
771 | 716 | } |
772 | 717 |
|
773 | | -static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa) |
| 718 | +int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa) |
774 | 719 | { |
| 720 | + struct inode *inode = d_inode(dentry); |
775 | 721 | struct ext4_inode_info *ei = EXT4_I(inode); |
| 722 | + u32 flags = ei->i_flags & EXT4_FL_USER_VISIBLE; |
776 | 723 |
|
777 | | - simple_fill_fsxattr(fa, ext4_iflags_to_xflags(ei->i_flags & |
778 | | - EXT4_FL_USER_VISIBLE)); |
| 724 | + if (S_ISREG(inode->i_mode)) |
| 725 | + flags &= ~FS_PROJINHERIT_FL; |
779 | 726 |
|
| 727 | + fileattr_fill_flags(fa, flags); |
780 | 728 | if (ext4_has_feature_project(inode->i_sb)) |
781 | 729 | fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid); |
| 730 | + |
| 731 | + return 0; |
| 732 | +} |
| 733 | + |
| 734 | +int ext4_fileattr_set(struct user_namespace *mnt_userns, |
| 735 | + struct dentry *dentry, struct fileattr *fa) |
| 736 | +{ |
| 737 | + struct inode *inode = d_inode(dentry); |
| 738 | + u32 flags = fa->flags; |
| 739 | + int err = -EOPNOTSUPP; |
| 740 | + |
| 741 | + ext4_fc_start_update(inode); |
| 742 | + if (flags & ~EXT4_FL_USER_VISIBLE) |
| 743 | + goto out; |
| 744 | + |
| 745 | + /* |
| 746 | + * chattr(1) grabs flags via GETFLAGS, modifies the result and |
| 747 | + * passes that to SETFLAGS. So we cannot easily make SETFLAGS |
| 748 | + * more restrictive than just silently masking off visible but |
| 749 | + * not settable flags as we always did. |
| 750 | + */ |
| 751 | + flags &= EXT4_FL_USER_MODIFIABLE; |
| 752 | + if (ext4_mask_flags(inode->i_mode, flags) != flags) |
| 753 | + goto out; |
| 754 | + err = ext4_ioctl_check_immutable(inode, fa->fsx_projid, flags); |
| 755 | + if (err) |
| 756 | + goto out; |
| 757 | + err = ext4_ioctl_setflags(inode, flags); |
| 758 | + if (err) |
| 759 | + goto out; |
| 760 | + err = ext4_ioctl_setproject(inode, fa->fsx_projid); |
| 761 | +out: |
| 762 | + ext4_fc_stop_update(inode); |
| 763 | + return err; |
782 | 764 | } |
783 | 765 |
|
784 | 766 | /* So that the fiemap access checks can't overflow on 32 bit machines. */ |
@@ -816,55 +798,13 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
816 | 798 | { |
817 | 799 | struct inode *inode = file_inode(filp); |
818 | 800 | struct super_block *sb = inode->i_sb; |
819 | | - struct ext4_inode_info *ei = EXT4_I(inode); |
820 | 801 | struct user_namespace *mnt_userns = file_mnt_user_ns(filp); |
821 | | - unsigned int flags; |
822 | 802 |
|
823 | 803 | ext4_debug("cmd = %u, arg = %lu\n", cmd, arg); |
824 | 804 |
|
825 | 805 | switch (cmd) { |
826 | 806 | case FS_IOC_GETFSMAP: |
827 | 807 | return ext4_ioc_getfsmap(sb, (void __user *)arg); |
828 | | - case FS_IOC_GETFLAGS: |
829 | | - flags = ei->i_flags & EXT4_FL_USER_VISIBLE; |
830 | | - if (S_ISREG(inode->i_mode)) |
831 | | - flags &= ~EXT4_PROJINHERIT_FL; |
832 | | - return put_user(flags, (int __user *) arg); |
833 | | - case FS_IOC_SETFLAGS: { |
834 | | - int err; |
835 | | - |
836 | | - if (!inode_owner_or_capable(mnt_userns, inode)) |
837 | | - return -EACCES; |
838 | | - |
839 | | - if (get_user(flags, (int __user *) arg)) |
840 | | - return -EFAULT; |
841 | | - |
842 | | - if (flags & ~EXT4_FL_USER_VISIBLE) |
843 | | - return -EOPNOTSUPP; |
844 | | - /* |
845 | | - * chattr(1) grabs flags via GETFLAGS, modifies the result and |
846 | | - * passes that to SETFLAGS. So we cannot easily make SETFLAGS |
847 | | - * more restrictive than just silently masking off visible but |
848 | | - * not settable flags as we always did. |
849 | | - */ |
850 | | - flags &= EXT4_FL_USER_MODIFIABLE; |
851 | | - if (ext4_mask_flags(inode->i_mode, flags) != flags) |
852 | | - return -EOPNOTSUPP; |
853 | | - |
854 | | - err = mnt_want_write_file(filp); |
855 | | - if (err) |
856 | | - return err; |
857 | | - |
858 | | - inode_lock(inode); |
859 | | - err = ext4_ioctl_check_immutable(inode, |
860 | | - from_kprojid(&init_user_ns, ei->i_projid), |
861 | | - flags); |
862 | | - if (!err) |
863 | | - err = ext4_ioctl_setflags(inode, flags); |
864 | | - inode_unlock(inode); |
865 | | - mnt_drop_write_file(filp); |
866 | | - return err; |
867 | | - } |
868 | 808 | case EXT4_IOC_GETVERSION: |
869 | 809 | case EXT4_IOC_GETVERSION_OLD: |
870 | 810 | return put_user(inode->i_generation, (int __user *) arg); |
@@ -1246,60 +1186,6 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1246 | 1186 | case EXT4_IOC_GET_ES_CACHE: |
1247 | 1187 | return ext4_ioctl_get_es_cache(filp, arg); |
1248 | 1188 |
|
1249 | | - case FS_IOC_FSGETXATTR: |
1250 | | - { |
1251 | | - struct fsxattr fa; |
1252 | | - |
1253 | | - ext4_fill_fsxattr(inode, &fa); |
1254 | | - |
1255 | | - if (copy_to_user((struct fsxattr __user *)arg, |
1256 | | - &fa, sizeof(fa))) |
1257 | | - return -EFAULT; |
1258 | | - return 0; |
1259 | | - } |
1260 | | - case FS_IOC_FSSETXATTR: |
1261 | | - { |
1262 | | - struct fsxattr fa, old_fa; |
1263 | | - int err; |
1264 | | - |
1265 | | - if (copy_from_user(&fa, (struct fsxattr __user *)arg, |
1266 | | - sizeof(fa))) |
1267 | | - return -EFAULT; |
1268 | | - |
1269 | | - /* Make sure caller has proper permission */ |
1270 | | - if (!inode_owner_or_capable(mnt_userns, inode)) |
1271 | | - return -EACCES; |
1272 | | - |
1273 | | - if (fa.fsx_xflags & ~EXT4_SUPPORTED_FS_XFLAGS) |
1274 | | - return -EOPNOTSUPP; |
1275 | | - |
1276 | | - flags = ext4_xflags_to_iflags(fa.fsx_xflags); |
1277 | | - if (ext4_mask_flags(inode->i_mode, flags) != flags) |
1278 | | - return -EOPNOTSUPP; |
1279 | | - |
1280 | | - err = mnt_want_write_file(filp); |
1281 | | - if (err) |
1282 | | - return err; |
1283 | | - |
1284 | | - inode_lock(inode); |
1285 | | - ext4_fill_fsxattr(inode, &old_fa); |
1286 | | - err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa); |
1287 | | - if (err) |
1288 | | - goto out; |
1289 | | - flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | |
1290 | | - (flags & EXT4_FL_XFLAG_VISIBLE); |
1291 | | - err = ext4_ioctl_check_immutable(inode, fa.fsx_projid, flags); |
1292 | | - if (err) |
1293 | | - goto out; |
1294 | | - err = ext4_ioctl_setflags(inode, flags); |
1295 | | - if (err) |
1296 | | - goto out; |
1297 | | - err = ext4_ioctl_setproject(filp, fa.fsx_projid); |
1298 | | -out: |
1299 | | - inode_unlock(inode); |
1300 | | - mnt_drop_write_file(filp); |
1301 | | - return err; |
1302 | | - } |
1303 | 1189 | case EXT4_IOC_SHUTDOWN: |
1304 | 1190 | return ext4_shutdown(sb, arg); |
1305 | 1191 |
|
@@ -1340,12 +1226,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1340 | 1226 | { |
1341 | 1227 | /* These are just misnamed, they actually get/put from/to user an int */ |
1342 | 1228 | switch (cmd) { |
1343 | | - case FS_IOC32_GETFLAGS: |
1344 | | - cmd = FS_IOC_GETFLAGS; |
1345 | | - break; |
1346 | | - case FS_IOC32_SETFLAGS: |
1347 | | - cmd = FS_IOC_SETFLAGS; |
1348 | | - break; |
1349 | 1229 | case EXT4_IOC32_GETVERSION: |
1350 | 1230 | cmd = EXT4_IOC_GETVERSION; |
1351 | 1231 | break; |
@@ -1405,8 +1285,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1405 | 1285 | case EXT4_IOC_CLEAR_ES_CACHE: |
1406 | 1286 | case EXT4_IOC_GETSTATE: |
1407 | 1287 | case EXT4_IOC_GET_ES_CACHE: |
1408 | | - case FS_IOC_FSGETXATTR: |
1409 | | - case FS_IOC_FSSETXATTR: |
1410 | 1288 | break; |
1411 | 1289 | default: |
1412 | 1290 | return -ENOIOCTLCMD; |
|
0 commit comments