History

Merge tag 'vfs-6.17-rc1.fileattr' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull fileattr updates from Christian Brauner: "This introduces the new file_getattr() and file_setattr() system calls after lengthy discussions. Both system calls serve as successors and extensible companions to the FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR system calls which have started to show their age in addition to being named in a way that makes it easy to conflate them with extended attribute related operations. These syscalls allow userspace to set filesystem inode attributes on special files. One of the usage examples is the XFS quota projects. XFS has project quotas which could be attached to a directory. All new inodes in these directories inherit project ID set on parent directory. The project is created from userspace by opening and calling FS_IOC_FSSETXATTR on each inode. This is not possible for special files such as FIFO, SOCK, BLK etc. Therefore, some inodes are left with empty project ID. Those inodes then are not shown in the quota accounting but still exist in the directory. This is not critical but in the case when special files are created in the directory with already existing project quota, these new inodes inherit extended attributes. This creates a mix of special files with and without attributes. Moreover, special files with attributes don't have a possibility to become clear or change the attributes. This, in turn, prevents userspace from re-creating quota project on these existing files. In addition, these new system calls allow the implementation of additional attributes that we couldn't or didn't want to fit into the legacy ioctls anymore" * tag 'vfs-6.17-rc1.fileattr' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: fs: tighten a sanity check in file_attr_to_fileattr() tree-wide: s/struct fileattr/struct file_kattr/g fs: introduce file_getattr and file_setattr syscalls fs: prepare for extending file_get/setattr() fs: make vfs_fileattr_[get|set] return -EOPNOTSUPP selinux: implement inode_file_[g|s]etattr hooks lsm: introduce new hooks for setting/getting inode fsxattr fs: split fileattr related helpers into separate file

Linus Torvalds committed 1 year ago

Commit 57fcb7d2 parents cec40a7 e85931d64 files · +752 −410Browse files

Unified · Split

64 files
  1. Documentation/filesystems/locking.rst +2 −2
  2. Documentation/filesystems/vfs.rst +2 −2
  3. arch/alpha/kernel/syscalls/syscall.tbl +2 −0
  4. arch/arm/tools/syscall.tbl +2 −0
  5. arch/arm64/tools/syscall_32.tbl +2 −0
  6. arch/m68k/kernel/syscalls/syscall.tbl +2 −0
  7. arch/microblaze/kernel/syscalls/syscall.tbl +2 −0
  8. arch/mips/kernel/syscalls/syscall_n32.tbl +2 −0
  9. arch/mips/kernel/syscalls/syscall_n64.tbl +2 −0
  10. arch/mips/kernel/syscalls/syscall_o32.tbl +2 −0
  11. arch/parisc/kernel/syscalls/syscall.tbl +2 −0
  12. arch/powerpc/kernel/syscalls/syscall.tbl +2 −0
  13. arch/s390/kernel/syscalls/syscall.tbl +2 −0
  14. arch/sh/kernel/syscalls/syscall.tbl +2 −0
  15. arch/sparc/kernel/syscalls/syscall.tbl +2 −0
  16. arch/x86/entry/syscalls/syscall_32.tbl +2 −0
  17. arch/x86/entry/syscalls/syscall_64.tbl +2 −0
  18. arch/xtensa/kernel/syscalls/syscall.tbl +2 −0
  19. fs/Makefile +2 −1
  20. fs/bcachefs/fs.c +2 −2
  21. fs/btrfs/ioctl.c +2 −2
  22. fs/btrfs/ioctl.h +3 −3
  23. fs/ecryptfs/inode.c +2 −2
  24. fs/efivarfs/inode.c +2 −2
  25. fs/ext2/ext2.h +2 −2
  26. fs/ext2/ioctl.c +2 −2
  27. fs/ext4/ext4.h +2 −2
  28. fs/ext4/ioctl.c +2 −2
  29. fs/f2fs/f2fs.h +2 −2
  30. fs/f2fs/file.c +2 −2
  31. fs/file_attr.c +498 −0
  32. fs/fuse/fuse_i.h +2 −2
  33. fs/fuse/ioctl.c +6 −2
  34. fs/gfs2/file.c +2 −2
  35. fs/gfs2/inode.h +2 −2
  36. fs/hfsplus/hfsplus_fs.h +2 −2
  37. fs/hfsplus/inode.c +2 −2
  38. fs/ioctl.c +0 −309
  39. fs/jfs/ioctl.c +2 −2
  40. fs/jfs/jfs_inode.h +2 −2
  41. fs/nilfs2/ioctl.c +2 −2
  42. fs/nilfs2/nilfs.h +2 −2
  43. fs/ocfs2/ioctl.c +2 −2
  44. fs/ocfs2/ioctl.h +2 −2
  45. fs/orangefs/inode.c +2 −2
  46. fs/overlayfs/copy_up.c +3 −3
  47. fs/overlayfs/inode.c +7 −10
  48. fs/overlayfs/overlayfs.h +5 −5
  49. fs/overlayfs/util.c +1 −1
  50. fs/ubifs/ioctl.c +2 −2
  51. fs/ubifs/ubifs.h +2 −2
  52. fs/xfs/xfs_ioctl.c +9 −9
  53. fs/xfs/xfs_ioctl.h +2 −2
  54. include/linux/fileattr.h +31 −7
  55. include/linux/fs.h +3 −3
  56. include/linux/lsm_hook_defs.h +2 −0
  57. include/linux/security.h +16 −0
  58. include/linux/syscalls.h +7 −0
  59. include/uapi/asm-generic/unistd.h +7 −1
  60. include/uapi/linux/fs.h +18 −0
  61. mm/shmem.c +2 −2
  62. scripts/syscall.tbl +2 −0
  63. security/security.c +30 −0
  64. security/selinux/hooks.c +14 −0
Documentation/filesystems/locking.rst+2−2
@@ -87,8 +87,8 @@ prototypes:: · 86 unmodified lines
8787 int (*tmpfile) (struct mnt_idmap *, struct inode *,
8888 struct file *, umode_t);
8989 int (*fileattr_set)(struct mnt_idmap *idmap,
90− struct dentry *dentry, struct fileattr *fa);
91− int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);
90+ struct dentry *dentry, struct file_kattr *fa);
91+ int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa);
9292 struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int);
9393 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
9494
Documentation/filesystems/vfs.rst+2−2
@@ -515,8 +515,8 @@ As of kernel 2.6.22, the following members are defined: · 514 unmodified lines
515515 struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int);
516516 int (*set_acl)(struct mnt_idmap *, struct dentry *, struct posix_acl *, int);
517517 int (*fileattr_set)(struct mnt_idmap *idmap,
518− struct dentry *dentry, struct fileattr *fa);
519− int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);
518+ struct dentry *dentry, struct file_kattr *fa);
519+ int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa);
520520 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
521521 };
522522
arch/alpha/kernel/syscalls/syscall.tbl+2−0
@@ -507,3 +507,5 @@ · 506 unmodified lines
507507 575 common listxattrat sys_listxattrat
508508 576 common removexattrat sys_removexattrat
509509 577 common open_tree_attr sys_open_tree_attr
510+578 common file_getattr sys_file_getattr
511+579 common file_setattr sys_file_setattr
arch/arm/tools/syscall.tbl+2−0
@@ -482,3 +482,5 @@ · 481 unmodified lines
482482 465 common listxattrat sys_listxattrat
483483 466 common removexattrat sys_removexattrat
484484 467 common open_tree_attr sys_open_tree_attr
485+468 common file_getattr sys_file_getattr
486+469 common file_setattr sys_file_setattr
arch/arm64/tools/syscall_32.tbl+2−0
@@ -479,3 +479,5 @@ · 478 unmodified lines
479479 465 common listxattrat sys_listxattrat
480480 466 common removexattrat sys_removexattrat
481481 467 common open_tree_attr sys_open_tree_attr
482+468 common file_getattr sys_file_getattr
483+469 common file_setattr sys_file_setattr
arch/m68k/kernel/syscalls/syscall.tbl+2−0
@@ -467,3 +467,5 @@ · 466 unmodified lines
467467 465 common listxattrat sys_listxattrat
468468 466 common removexattrat sys_removexattrat
469469 467 common open_tree_attr sys_open_tree_attr
470+468 common file_getattr sys_file_getattr
471+469 common file_setattr sys_file_setattr
arch/microblaze/kernel/syscalls/syscall.tbl+2−0
@@ -473,3 +473,5 @@ · 472 unmodified lines
473473 465 common listxattrat sys_listxattrat
474474 466 common removexattrat sys_removexattrat
475475 467 common open_tree_attr sys_open_tree_attr
476+468 common file_getattr sys_file_getattr
477+469 common file_setattr sys_file_setattr
arch/mips/kernel/syscalls/syscall_n32.tbl+2−0
@@ -406,3 +406,5 @@ · 405 unmodified lines
406406 465 n32 listxattrat sys_listxattrat
407407 466 n32 removexattrat sys_removexattrat
408408 467 n32 open_tree_attr sys_open_tree_attr
409+468 n32 file_getattr sys_file_getattr
410+469 n32 file_setattr sys_file_setattr
arch/mips/kernel/syscalls/syscall_n64.tbl+2−0
@@ -382,3 +382,5 @@ · 381 unmodified lines
382382 465 n64 listxattrat sys_listxattrat
383383 466 n64 removexattrat sys_removexattrat
384384 467 n64 open_tree_attr sys_open_tree_attr
385+468 n64 file_getattr sys_file_getattr
386+469 n64 file_setattr sys_file_setattr
arch/mips/kernel/syscalls/syscall_o32.tbl+2−0
@@ -455,3 +455,5 @@ · 454 unmodified lines
455455 465 o32 listxattrat sys_listxattrat
456456 466 o32 removexattrat sys_removexattrat
457457 467 o32 open_tree_attr sys_open_tree_attr
458+468 o32 file_getattr sys_file_getattr
459+469 o32 file_setattr sys_file_setattr
arch/parisc/kernel/syscalls/syscall.tbl+2−0
@@ -466,3 +466,5 @@ · 465 unmodified lines
466466 465 common listxattrat sys_listxattrat
467467 466 common removexattrat sys_removexattrat
468468 467 common open_tree_attr sys_open_tree_attr
469+468 common file_getattr sys_file_getattr
470+469 common file_setattr sys_file_setattr
arch/powerpc/kernel/syscalls/syscall.tbl+2−0
@@ -558,3 +558,5 @@ · 557 unmodified lines
558558 465 common listxattrat sys_listxattrat
559559 466 common removexattrat sys_removexattrat
560560 467 common open_tree_attr sys_open_tree_attr
561+468 common file_getattr sys_file_getattr
562+469 common file_setattr sys_file_setattr
arch/s390/kernel/syscalls/syscall.tbl+2−0
@@ -470,3 +470,5 @@ · 469 unmodified lines
470470 465 common listxattrat sys_listxattrat sys_listxattrat
471471 466 common removexattrat sys_removexattrat sys_removexattrat
472472 467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr
473+468 common file_getattr sys_file_getattr sys_file_getattr
474+469 common file_setattr sys_file_setattr sys_file_setattr
arch/sh/kernel/syscalls/syscall.tbl+2−0
@@ -471,3 +471,5 @@ · 470 unmodified lines
471471 465 common listxattrat sys_listxattrat
472472 466 common removexattrat sys_removexattrat
473473 467 common open_tree_attr sys_open_tree_attr
474+468 common file_getattr sys_file_getattr
475+469 common file_setattr sys_file_setattr
arch/sparc/kernel/syscalls/syscall.tbl+2−0
@@ -513,3 +513,5 @@ · 512 unmodified lines
513513 465 common listxattrat sys_listxattrat
514514 466 common removexattrat sys_removexattrat
515515 467 common open_tree_attr sys_open_tree_attr
516+468 common file_getattr sys_file_getattr
517+469 common file_setattr sys_file_setattr
arch/x86/entry/syscalls/syscall_32.tbl+2−0
@@ -473,3 +473,5 @@ · 472 unmodified lines
473473 465 i386 listxattrat sys_listxattrat
474474 466 i386 removexattrat sys_removexattrat
475475 467 i386 open_tree_attr sys_open_tree_attr
476+468 i386 file_getattr sys_file_getattr
477+469 i386 file_setattr sys_file_setattr
arch/x86/entry/syscalls/syscall_64.tbl+2−0
@@ -391,6 +391,8 @@ · 390 unmodified lines
391391 465 common listxattrat sys_listxattrat
392392 466 common removexattrat sys_removexattrat
393393 467 common open_tree_attr sys_open_tree_attr
394+468 common file_getattr sys_file_getattr
395+469 common file_setattr sys_file_setattr
394396
395397 #
396398 # Due to a historical design error, certain syscalls are numbered differently
arch/xtensa/kernel/syscalls/syscall.tbl+2−0
@@ -438,3 +438,5 @@ · 437 unmodified lines
438438 465 common listxattrat sys_listxattrat
439439 466 common removexattrat sys_removexattrat
440440 467 common open_tree_attr sys_open_tree_attr
441+468 common file_getattr sys_file_getattr
442+469 common file_setattr sys_file_setattr
fs/Makefile+2−1
@@ -15,7 +15,8 @@ obj-y := open.o read_write.o file_table.o super.o \ · 14 unmodified lines
1515 pnode.o splice.o sync.o utimes.o d_path.o \
1616 stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
1717 fs_types.o fs_context.o fs_parser.o fsopen.o init.o \
18− kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o
18+ kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o \
19+ file_attr.o
1920
2021 obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o
2122 obj-$(CONFIG_PROC_FS) += proc_namespace.o
fs/bcachefs/fs.c+2−2
@@ -1617,7 +1617,7 @@ static const __maybe_unused unsigned bch_flags_to_xflags[] = { · 1616 unmodified lines
16171617 };
16181618
16191619 static int bch2_fileattr_get(struct dentry *dentry,
1620− struct fileattr *fa)
1620+ struct file_kattr *fa)
16211621 {
16221622 struct bch_inode_info *inode = to_bch_ei(d_inode(dentry));
16231623 struct bch_fs *c = inode->v.i_sb->s_fs_info;
@@ -1680,7 +1680,7 @@ static int fssetxattr_inode_update_fn(struct btree_trans *trans, · 56 unmodified lines
16801680
16811681 static int bch2_fileattr_set(struct mnt_idmap *idmap,
16821682 struct dentry *dentry,
1683− struct fileattr *fa)
1683+ struct file_kattr *fa)
16841684 {
16851685 struct bch_inode_info *inode = to_bch_ei(d_inode(dentry));
16861686 struct bch_fs *c = inode->v.i_sb->s_fs_info;
fs/btrfs/ioctl.c+2−2
@@ -245,7 +245,7 @@ static int btrfs_check_ioctl_vol_args2_subvol_name(const struct btrfs_ioctl_vol_ · 244 unmodified lines
245245 * Set flags/xflags from the internal inode flags. The remaining items of
246246 * fsxattr are zeroed.
247247 */
248−int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
248+int btrfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
249249 {
250250 const struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
251251
@@ -254,7 +254,7 @@ int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 2 unmodified lines
254254 }
255255
256256 int btrfs_fileattr_set(struct mnt_idmap *idmap,
257− struct dentry *dentry, struct fileattr *fa)
257+ struct dentry *dentry, struct file_kattr *fa)
258258 {
259259 struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
260260 struct btrfs_root *root = inode->root;
fs/btrfs/ioctl.h+3−3
@@ -8,7 +8,7 @@ · 7 unmodified lines
88 struct file;
99 struct dentry;
1010 struct mnt_idmap;
11−struct fileattr;
11+struct file_kattr;
1212 struct io_uring_cmd;
1313 struct btrfs_inode;
1414 struct btrfs_fs_info;
@@ -16,9 +16,9 @@ struct btrfs_ioctl_balance_args; · 1 unmodified line
1616
1717 long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
1818 long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
19−int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
19+int btrfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
2020 int btrfs_fileattr_set(struct mnt_idmap *idmap,
21− struct dentry *dentry, struct fileattr *fa);
21+ struct dentry *dentry, struct file_kattr *fa);
2222 int btrfs_ioctl_get_supported_features(void __user *arg);
2323 void btrfs_sync_inode_flags_to_i_flags(struct btrfs_inode *inode);
2424 void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
fs/ecryptfs/inode.c+2−2
@@ -1124,13 +1124,13 @@ out: · 1123 unmodified lines
11241124 return rc;
11251125 }
11261126
1127−static int ecryptfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
1127+static int ecryptfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
11281128 {
11291129 return vfs_fileattr_get(ecryptfs_dentry_to_lower(dentry), fa);
11301130 }
11311131
11321132 static int ecryptfs_fileattr_set(struct mnt_idmap *idmap,
1133− struct dentry *dentry, struct fileattr *fa)
1133+ struct dentry *dentry, struct file_kattr *fa)
11341134 {
11351135 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
11361136 int rc;
fs/efivarfs/inode.c+2−2
@@ -138,7 +138,7 @@ const struct inode_operations efivarfs_dir_inode_operations = { · 137 unmodified lines
138138 };
139139
140140 static int
141−efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
141+efivarfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
142142 {
143143 unsigned int i_flags;
144144 unsigned int flags = 0;
@@ -154,7 +154,7 @@ efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 9 unmodified lines
154154
155155 static int
156156 efivarfs_fileattr_set(struct mnt_idmap *idmap,
157− struct dentry *dentry, struct fileattr *fa)
157+ struct dentry *dentry, struct file_kattr *fa)
158158 {
159159 unsigned int i_flags = 0;
160160
fs/ext2/ext2.h+2−2
@@ -750,9 +750,9 @@ extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, · 749 unmodified lines
750750 u64 start, u64 len);
751751
752752 /* ioctl.c */
753−extern int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa);
753+extern int ext2_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
754754 extern int ext2_fileattr_set(struct mnt_idmap *idmap,
755− struct dentry *dentry, struct fileattr *fa);
755+ struct dentry *dentry, struct file_kattr *fa);
756756 extern long ext2_ioctl(struct file *, unsigned int, unsigned long);
757757 extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);
758758
fs/ext2/ioctl.c+2−2
@@ -18,7 +18,7 @@ · 17 unmodified lines
1818 #include <linux/uaccess.h>
1919 #include <linux/fileattr.h>
2020
21−int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa)
21+int ext2_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
2222 {
2323 struct ext2_inode_info *ei = EXT2_I(d_inode(dentry));
2424
@@ -28,7 +28,7 @@ int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 3 unmodified lines
2828 }
2929
3030 int ext2_fileattr_set(struct mnt_idmap *idmap,
31− struct dentry *dentry, struct fileattr *fa)
31+ struct dentry *dentry, struct file_kattr *fa)
3232 {
3333 struct inode *inode = d_inode(dentry);
3434 struct ext2_inode_info *ei = EXT2_I(inode);
fs/ext4/ext4.h+2−2
@@ -3103,8 +3103,8 @@ extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode, · 3102 unmodified lines
31033103 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
31043104 extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
31053105 int ext4_fileattr_set(struct mnt_idmap *idmap,
3106− struct dentry *dentry, struct fileattr *fa);
3107−int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa);
3106+ struct dentry *dentry, struct file_kattr *fa);
3107+int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
31083108 extern void ext4_reset_inode_seed(struct inode *inode);
31093109 int ext4_update_overhead(struct super_block *sb, bool force);
31103110 int ext4_force_shutdown(struct super_block *sb, u32 flags);
fs/ext4/ioctl.c+2−2
@@ -980,7 +980,7 @@ group_add_out: · 979 unmodified lines
980980 return err;
981981 }
982982
983−int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa)
983+int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
984984 {
985985 struct inode *inode = d_inode(dentry);
986986 struct ext4_inode_info *ei = EXT4_I(inode);
@@ -997,7 +997,7 @@ int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 10 unmodified lines
997997 }
998998
999999 int ext4_fileattr_set(struct mnt_idmap *idmap,
1000− struct dentry *dentry, struct fileattr *fa)
1000+ struct dentry *dentry, struct file_kattr *fa)
10011001 {
10021002 struct inode *inode = d_inode(dentry);
10031003 u32 flags = fa->flags;
fs/f2fs/f2fs.h+2−2
@@ -3615,9 +3615,9 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count); · 3614 unmodified lines
36153615 int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
36163616 bool readonly, bool need_lock);
36173617 int f2fs_precache_extents(struct inode *inode);
3618−int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
3618+int f2fs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
36193619 int f2fs_fileattr_set(struct mnt_idmap *idmap,
3620− struct dentry *dentry, struct fileattr *fa);
3620+ struct dentry *dentry, struct file_kattr *fa);
36213621 long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
36223622 long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
36233623 int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid);
fs/f2fs/file.c+2−2
@@ -3391,7 +3391,7 @@ static int f2fs_ioc_setproject(struct inode *inode, __u32 projid) · 3390 unmodified lines
33913391 }
33923392 #endif
33933393
3394−int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
3394+int f2fs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
33953395 {
33963396 struct inode *inode = d_inode(dentry);
33973397 struct f2fs_inode_info *fi = F2FS_I(inode);
@@ -3415,7 +3415,7 @@ int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 17 unmodified lines
34153415 }
34163416
34173417 int f2fs_fileattr_set(struct mnt_idmap *idmap,
3418− struct dentry *dentry, struct fileattr *fa)
3418+ struct dentry *dentry, struct file_kattr *fa)
34193419 {
34203420 struct inode *inode = d_inode(dentry);
34213421 u32 fsflags = fa->flags, mask = F2FS_SETTABLE_FS_FL;
fs/file_attr.c+498−0
@@ -0,0 +1,498 @@
1+// SPDX-License-Identifier: GPL-2.0
2+#include <linux/fs.h>
3+#include <linux/security.h>
4+#include <linux/fscrypt.h>
5+#include <linux/fileattr.h>
6+#include <linux/export.h>
7+#include <linux/syscalls.h>
8+#include <linux/namei.h>
9+
10+#include "internal.h"
11+
12+/**
13+ * fileattr_fill_xflags - initialize fileattr with xflags
14+ * @fa: fileattr pointer
15+ * @xflags: FS_XFLAG_* flags
16+ *
17+ * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). All
18+ * other fields are zeroed.
19+ */
20+void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags)
21+{
22+ memset(fa, 0, sizeof(*fa));
23+ fa->fsx_valid = true;
24+ fa->fsx_xflags = xflags;
25+ if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE)
26+ fa->flags |= FS_IMMUTABLE_FL;
27+ if (fa->fsx_xflags & FS_XFLAG_APPEND)
28+ fa->flags |= FS_APPEND_FL;
29+ if (fa->fsx_xflags & FS_XFLAG_SYNC)
30+ fa->flags |= FS_SYNC_FL;
31+ if (fa->fsx_xflags & FS_XFLAG_NOATIME)
32+ fa->flags |= FS_NOATIME_FL;
33+ if (fa->fsx_xflags & FS_XFLAG_NODUMP)
34+ fa->flags |= FS_NODUMP_FL;
35+ if (fa->fsx_xflags & FS_XFLAG_DAX)
36+ fa->flags |= FS_DAX_FL;
37+ if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
38+ fa->flags |= FS_PROJINHERIT_FL;
39+}
40+EXPORT_SYMBOL(fileattr_fill_xflags);
41+
42+/**
43+ * fileattr_fill_flags - initialize fileattr with flags
44+ * @fa: fileattr pointer
45+ * @flags: FS_*_FL flags
46+ *
47+ * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags).
48+ * All other fields are zeroed.
49+ */
50+void fileattr_fill_flags(struct file_kattr *fa, u32 flags)
51+{
52+ memset(fa, 0, sizeof(*fa));
53+ fa->flags_valid = true;
54+ fa->flags = flags;
55+ if (fa->flags & FS_SYNC_FL)
56+ fa->fsx_xflags |= FS_XFLAG_SYNC;
57+ if (fa->flags & FS_IMMUTABLE_FL)
58+ fa->fsx_xflags |= FS_XFLAG_IMMUTABLE;
59+ if (fa->flags & FS_APPEND_FL)
60+ fa->fsx_xflags |= FS_XFLAG_APPEND;
61+ if (fa->flags & FS_NODUMP_FL)
62+ fa->fsx_xflags |= FS_XFLAG_NODUMP;
63+ if (fa->flags & FS_NOATIME_FL)
64+ fa->fsx_xflags |= FS_XFLAG_NOATIME;
65+ if (fa->flags & FS_DAX_FL)
66+ fa->fsx_xflags |= FS_XFLAG_DAX;
67+ if (fa->flags & FS_PROJINHERIT_FL)
68+ fa->fsx_xflags |= FS_XFLAG_PROJINHERIT;
69+}
70+EXPORT_SYMBOL(fileattr_fill_flags);
71+
72+/**
73+ * vfs_fileattr_get - retrieve miscellaneous file attributes
74+ * @dentry: the object to retrieve from
75+ * @fa: fileattr pointer
76+ *
77+ * Call i_op->fileattr_get() callback, if exists.
78+ *
79+ * Return: 0 on success, or a negative error on failure.
80+ */
81+int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
82+{
83+ struct inode *inode = d_inode(dentry);
84+ int error;
85+
86+ if (!inode->i_op->fileattr_get)
87+ return -EOPNOTSUPP;
88+
89+ error = security_inode_file_getattr(dentry, fa);
90+ if (error)
91+ return error;
92+
93+ return inode->i_op->fileattr_get(dentry, fa);
94+}
95+EXPORT_SYMBOL(vfs_fileattr_get);
96+
97+static void fileattr_to_file_attr(const struct file_kattr *fa,
98+ struct file_attr *fattr)
99+{
100+ __u32 mask = FS_XFLAGS_MASK;
101+
102+ memset(fattr, 0, sizeof(struct file_attr));
103+ fattr->fa_xflags = fa->fsx_xflags & mask;
104+ fattr->fa_extsize = fa->fsx_extsize;
105+ fattr->fa_nextents = fa->fsx_nextents;
106+ fattr->fa_projid = fa->fsx_projid;
107+ fattr->fa_cowextsize = fa->fsx_cowextsize;
108+}
109+
110+/**
111+ * copy_fsxattr_to_user - copy fsxattr to userspace.
112+ * @fa: fileattr pointer
113+ * @ufa: fsxattr user pointer
114+ *
115+ * Return: 0 on success, or -EFAULT on failure.
116+ */
117+int copy_fsxattr_to_user(const struct file_kattr *fa, struct fsxattr __user *ufa)
118+{
119+ struct fsxattr xfa;
120+ __u32 mask = FS_XFLAGS_MASK;
121+
122+ memset(&xfa, 0, sizeof(xfa));
123+ xfa.fsx_xflags = fa->fsx_xflags & mask;
124+ xfa.fsx_extsize = fa->fsx_extsize;
125+ xfa.fsx_nextents = fa->fsx_nextents;
126+ xfa.fsx_projid = fa->fsx_projid;
127+ xfa.fsx_cowextsize = fa->fsx_cowextsize;
128+
129+ if (copy_to_user(ufa, &xfa, sizeof(xfa)))
130+ return -EFAULT;
131+
132+ return 0;
133+}
134+EXPORT_SYMBOL(copy_fsxattr_to_user);
135+
136+static int file_attr_to_fileattr(const struct file_attr *fattr,
137+ struct file_kattr *fa)
138+{
139+ __u64 mask = FS_XFLAGS_MASK;
140+
141+ if (fattr->fa_xflags & ~mask)
142+ return -EINVAL;
143+
144+ fileattr_fill_xflags(fa, fattr->fa_xflags);
145+ fa->fsx_xflags &= ~FS_XFLAG_RDONLY_MASK;
146+ fa->fsx_extsize = fattr->fa_extsize;
147+ fa->fsx_projid = fattr->fa_projid;
148+ fa->fsx_cowextsize = fattr->fa_cowextsize;
149+
150+ return 0;
151+}
152+
153+static int copy_fsxattr_from_user(struct file_kattr *fa,
154+ struct fsxattr __user *ufa)
155+{
156+ struct fsxattr xfa;
157+ __u32 mask = FS_XFLAGS_MASK;
158+
159+ if (copy_from_user(&xfa, ufa, sizeof(xfa)))
160+ return -EFAULT;
161+
162+ if (xfa.fsx_xflags & ~mask)
163+ return -EOPNOTSUPP;
164+
165+ fileattr_fill_xflags(fa, xfa.fsx_xflags);
166+ fa->fsx_xflags &= ~FS_XFLAG_RDONLY_MASK;
167+ fa->fsx_extsize = xfa.fsx_extsize;
168+ fa->fsx_nextents = xfa.fsx_nextents;
169+ fa->fsx_projid = xfa.fsx_projid;
170+ fa->fsx_cowextsize = xfa.fsx_cowextsize;
171+
172+ return 0;
173+}
174+
175+/*
176+ * Generic function to check FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS values and reject
177+ * any invalid configurations.
178+ *
179+ * Note: must be called with inode lock held.
180+ */
181+static int fileattr_set_prepare(struct inode *inode,
182+ const struct file_kattr *old_ma,
183+ struct file_kattr *fa)
184+{
185+ int err;
186+
187+ /*
188+ * The IMMUTABLE and APPEND_ONLY flags can only be changed by
189+ * the relevant capability.
190+ */
191+ if ((fa->flags ^ old_ma->flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
192+ !capable(CAP_LINUX_IMMUTABLE))
193+ return -EPERM;
194+
195+ err = fscrypt_prepare_setflags(inode, old_ma->flags, fa->flags);
196+ if (err)
197+ return err;
198+
199+ /*
200+ * Project Quota ID state is only allowed to change from within the init
201+ * namespace. Enforce that restriction only if we are trying to change
202+ * the quota ID state. Everything else is allowed in user namespaces.
203+ */
204+ if (current_user_ns() != &init_user_ns) {
205+ if (old_ma->fsx_projid != fa->fsx_projid)
206+ return -EINVAL;
207+ if ((old_ma->fsx_xflags ^ fa->fsx_xflags) &
208+ FS_XFLAG_PROJINHERIT)
209+ return -EINVAL;
210+ } else {
211+ /*
212+ * Caller is allowed to change the project ID. If it is being
213+ * changed, make sure that the new value is valid.
214+ */
215+ if (old_ma->fsx_projid != fa->fsx_projid &&
216+ !projid_valid(make_kprojid(&init_user_ns, fa->fsx_projid)))
217+ return -EINVAL;
218+ }
219+
220+ /* Check extent size hints. */
221+ if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode))
222+ return -EINVAL;
223+
224+ if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) &&
225+ !S_ISDIR(inode->i_mode))
226+ return -EINVAL;
227+
228+ if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
229+ !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
230+ return -EINVAL;
231+
232+ /*
233+ * It is only valid to set the DAX flag on regular files and
234+ * directories on filesystems.
235+ */
236+ if ((fa->fsx_xflags & FS_XFLAG_DAX) &&
237+ !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
238+ return -EINVAL;
239+
240+ /* Extent size hints of zero turn off the flags. */
241+ if (fa->fsx_extsize == 0)
242+ fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT);
243+ if (fa->fsx_cowextsize == 0)
244+ fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE;
245+
246+ return 0;
247+}
248+
249+/**
250+ * vfs_fileattr_set - change miscellaneous file attributes
251+ * @idmap: idmap of the mount
252+ * @dentry: the object to change
253+ * @fa: fileattr pointer
254+ *
255+ * After verifying permissions, call i_op->fileattr_set() callback, if
256+ * exists.
257+ *
258+ * Verifying attributes involves retrieving current attributes with
259+ * i_op->fileattr_get(), this also allows initializing attributes that have
260+ * not been set by the caller to current values. Inode lock is held
261+ * thoughout to prevent racing with another instance.
262+ *
263+ * Return: 0 on success, or a negative error on failure.
264+ */
265+int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
266+ struct file_kattr *fa)
267+{
268+ struct inode *inode = d_inode(dentry);
269+ struct file_kattr old_ma = {};
270+ int err;
271+
272+ if (!inode->i_op->fileattr_set)
273+ return -EOPNOTSUPP;
274+
275+ if (!inode_owner_or_capable(idmap, inode))
276+ return -EPERM;
277+
278+ inode_lock(inode);
279+ err = vfs_fileattr_get(dentry, &old_ma);
280+ if (!err) {
281+ /* initialize missing bits from old_ma */
282+ if (fa->flags_valid) {
283+ fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON;
284+ fa->fsx_extsize = old_ma.fsx_extsize;
285+ fa->fsx_nextents = old_ma.fsx_nextents;
286+ fa->fsx_projid = old_ma.fsx_projid;
287+ fa->fsx_cowextsize = old_ma.fsx_cowextsize;
288+ } else {
289+ fa->flags |= old_ma.flags & ~FS_COMMON_FL;
290+ }
291+
292+ err = fileattr_set_prepare(inode, &old_ma, fa);
293+ if (err)
294+ goto out;
295+ err = security_inode_file_setattr(dentry, fa);
296+ if (err)
297+ goto out;
298+ err = inode->i_op->fileattr_set(idmap, dentry, fa);
299+ if (err)
300+ goto out;
301+ }
302+
303+out:
304+ inode_unlock(inode);
305+ return err;
306+}
307+EXPORT_SYMBOL(vfs_fileattr_set);
308+
309+int ioctl_getflags(struct file *file, unsigned int __user *argp)
310+{
311+ struct file_kattr fa = { .flags_valid = true }; /* hint only */
312+ int err;
313+
314+ err = vfs_fileattr_get(file->f_path.dentry, &fa);
315+ if (err == -EOPNOTSUPP)
316+ err = -ENOIOCTLCMD;
317+ if (!err)
318+ err = put_user(fa.flags, argp);
319+ return err;
320+}
321+EXPORT_SYMBOL(ioctl_getflags);
322+
323+int ioctl_setflags(struct file *file, unsigned int __user *argp)
324+{
325+ struct mnt_idmap *idmap = file_mnt_idmap(file);
326+ struct dentry *dentry = file->f_path.dentry;
327+ struct file_kattr fa;
328+ unsigned int flags;
329+ int err;
330+
331+ err = get_user(flags, argp);
332+ if (!err) {
333+ err = mnt_want_write_file(file);
334+ if (!err) {
335+ fileattr_fill_flags(&fa, flags);
336+ err = vfs_fileattr_set(idmap, dentry, &fa);
337+ mnt_drop_write_file(file);
338+ if (err == -EOPNOTSUPP)
339+ err = -ENOIOCTLCMD;
340+ }
341+ }
342+ return err;
343+}
344+EXPORT_SYMBOL(ioctl_setflags);
345+
346+int ioctl_fsgetxattr(struct file *file, void __user *argp)
347+{
348+ struct file_kattr fa = { .fsx_valid = true }; /* hint only */
349+ int err;
350+
351+ err = vfs_fileattr_get(file->f_path.dentry, &fa);
352+ if (err == -EOPNOTSUPP)
353+ err = -ENOIOCTLCMD;
354+ if (!err)
355+ err = copy_fsxattr_to_user(&fa, argp);
356+
357+ return err;
358+}
359+EXPORT_SYMBOL(ioctl_fsgetxattr);
360+
361+int ioctl_fssetxattr(struct file *file, void __user *argp)
362+{
363+ struct mnt_idmap *idmap = file_mnt_idmap(file);
364+ struct dentry *dentry = file->f_path.dentry;
365+ struct file_kattr fa;
366+ int err;
367+
368+ err = copy_fsxattr_from_user(&fa, argp);
369+ if (!err) {
370+ err = mnt_want_write_file(file);
371+ if (!err) {
372+ err = vfs_fileattr_set(idmap, dentry, &fa);
373+ mnt_drop_write_file(file);
374+ if (err == -EOPNOTSUPP)
375+ err = -ENOIOCTLCMD;
376+ }
377+ }
378+ return err;
379+}
380+EXPORT_SYMBOL(ioctl_fssetxattr);
381+
382+SYSCALL_DEFINE5(file_getattr, int, dfd, const char __user *, filename,
383+ struct file_attr __user *, ufattr, size_t, usize,
384+ unsigned int, at_flags)
385+{
386+ struct path filepath __free(path_put) = {};
387+ struct filename *name __free(putname) = NULL;
388+ unsigned int lookup_flags = 0;
389+ struct file_attr fattr;
390+ struct file_kattr fa;
391+ int error;
392+
393+ BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0);
394+ BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST);
395+
396+ if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
397+ return -EINVAL;
398+
399+ if (!(at_flags & AT_SYMLINK_NOFOLLOW))
400+ lookup_flags |= LOOKUP_FOLLOW;
401+
402+ if (usize > PAGE_SIZE)
403+ return -E2BIG;
404+
405+ if (usize < FILE_ATTR_SIZE_VER0)
406+ return -EINVAL;
407+
408+ name = getname_maybe_null(filename, at_flags);
409+ if (IS_ERR(name))
410+ return PTR_ERR(name);
411+
412+ if (!name && dfd >= 0) {
413+ CLASS(fd, f)(dfd);
414+ if (fd_empty(f))
415+ return -EBADF;
416+
417+ filepath = fd_file(f)->f_path;
418+ path_get(&filepath);
419+ } else {
420+ error = filename_lookup(dfd, name, lookup_flags, &filepath,
421+ NULL);
422+ if (error)
423+ return error;
424+ }
425+
426+ error = vfs_fileattr_get(filepath.dentry, &fa);
427+ if (error)
428+ return error;
429+
430+ fileattr_to_file_attr(&fa, &fattr);
431+ error = copy_struct_to_user(ufattr, usize, &fattr,
432+ sizeof(struct file_attr), NULL);
433+
434+ return error;
435+}
436+
437+SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename,
438+ struct file_attr __user *, ufattr, size_t, usize,
439+ unsigned int, at_flags)
440+{
441+ struct path filepath __free(path_put) = {};
442+ struct filename *name __free(putname) = NULL;
443+ unsigned int lookup_flags = 0;
444+ struct file_attr fattr;
445+ struct file_kattr fa;
446+ int error;
447+
448+ BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0);
449+ BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST);
450+
451+ if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
452+ return -EINVAL;
453+
454+ if (!(at_flags & AT_SYMLINK_NOFOLLOW))
455+ lookup_flags |= LOOKUP_FOLLOW;
456+
457+ if (usize > PAGE_SIZE)
458+ return -E2BIG;
459+
460+ if (usize < FILE_ATTR_SIZE_VER0)
461+ return -EINVAL;
462+
463+ error = copy_struct_from_user(&fattr, sizeof(struct file_attr), ufattr,
464+ usize);
465+ if (error)
466+ return error;
467+
468+ error = file_attr_to_fileattr(&fattr, &fa);
469+ if (error)
470+ return error;
471+
472+ name = getname_maybe_null(filename, at_flags);
473+ if (IS_ERR(name))
474+ return PTR_ERR(name);
475+
476+ if (!name && dfd >= 0) {
477+ CLASS(fd, f)(dfd);
478+ if (fd_empty(f))
479+ return -EBADF;
480+
481+ filepath = fd_file(f)->f_path;
482+ path_get(&filepath);
483+ } else {
484+ error = filename_lookup(dfd, name, lookup_flags, &filepath,
485+ NULL);
486+ if (error)
487+ return error;
488+ }
489+
490+ error = mnt_want_write(filepath.mnt);
491+ if (!error) {
492+ error = vfs_fileattr_set(mnt_idmap(filepath.mnt),
493+ filepath.dentry, &fa);
494+ mnt_drop_write(filepath.mnt);
495+ }
496+
497+ return error;
498+}
fs/fuse/fuse_i.h+2−2
@@ -1479,9 +1479,9 @@ void fuse_dax_cancel_work(struct fuse_conn *fc); · 1478 unmodified lines
14791479 long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
14801480 long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
14811481 unsigned long arg);
1482−int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa);
1482+int fuse_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
14831483 int fuse_fileattr_set(struct mnt_idmap *idmap,
1484− struct dentry *dentry, struct fileattr *fa);
1484+ struct dentry *dentry, struct file_kattr *fa);
14851485
14861486 /* iomode.c */
14871487 int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff);
fs/fuse/ioctl.c+6−2
@@ -502,7 +502,7 @@ static void fuse_priv_ioctl_cleanup(struct inode *inode, struct fuse_file *ff) · 501 unmodified lines
502502 fuse_file_release(inode, ff, O_RDONLY, NULL, S_ISDIR(inode->i_mode));
503503 }
504504
505−int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa)
505+int fuse_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
506506 {
507507 struct inode *inode = d_inode(dentry);
508508 struct fuse_file *ff;
@@ -536,11 +536,13 @@ int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 27 unmodified lines
536536 cleanup:
537537 fuse_priv_ioctl_cleanup(inode, ff);
538538
539+ if (err == -ENOTTY)
540+ err = -EOPNOTSUPP;
539541 return err;
540542 }
541543
542544 int fuse_fileattr_set(struct mnt_idmap *idmap,
543− struct dentry *dentry, struct fileattr *fa)
545+ struct dentry *dentry, struct file_kattr *fa)
544546 {
545547 struct inode *inode = d_inode(dentry);
546548 struct fuse_file *ff;
@@ -572,5 +574,7 @@ int fuse_fileattr_set(struct mnt_idmap *idmap, · 25 unmodified lines
572574 cleanup:
573575 fuse_priv_ioctl_cleanup(inode, ff);
574576
577+ if (err == -ENOTTY)
578+ err = -EOPNOTSUPP;
575579 return err;
576580 }
fs/gfs2/file.c+2−2
@@ -155,7 +155,7 @@ static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags) · 154 unmodified lines
155155 return fsflags;
156156 }
157157
158−int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa)
158+int gfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
159159 {
160160 struct inode *inode = d_inode(dentry);
161161 struct gfs2_inode *ip = GFS2_I(inode);
@@ -276,7 +276,7 @@ out: · 114 unmodified lines
276276 }
277277
278278 int gfs2_fileattr_set(struct mnt_idmap *idmap,
279− struct dentry *dentry, struct fileattr *fa)
279+ struct dentry *dentry, struct file_kattr *fa)
280280 {
281281 struct inode *inode = d_inode(dentry);
282282 u32 fsflags = fa->flags, gfsflags = 0;
fs/gfs2/inode.h+2−2
@@ -107,9 +107,9 @@ loff_t gfs2_seek_hole(struct file *file, loff_t offset); · 106 unmodified lines
107107 extern const struct file_operations gfs2_file_fops_nolock;
108108 extern const struct file_operations gfs2_dir_fops_nolock;
109109
110−int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);
110+int gfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
111111 int gfs2_fileattr_set(struct mnt_idmap *idmap,
112− struct dentry *dentry, struct fileattr *fa);
112+ struct dentry *dentry, struct file_kattr *fa);
113113 void gfs2_set_inode_flags(struct inode *inode);
114114
115115 #ifdef CONFIG_GFS2_FS_LOCKING_DLM
fs/hfsplus/hfsplus_fs.h+2−2
@@ -491,9 +491,9 @@ int hfsplus_getattr(struct mnt_idmap *idmap, const struct path *path, · 490 unmodified lines
491491 unsigned int query_flags);
492492 int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
493493 int datasync);
494−int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa);
494+int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
495495 int hfsplus_fileattr_set(struct mnt_idmap *idmap,
496− struct dentry *dentry, struct fileattr *fa);
496+ struct dentry *dentry, struct file_kattr *fa);
497497
498498 /* ioctl.c */
499499 long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
fs/hfsplus/inode.c+2−2
@@ -656,7 +656,7 @@ out: · 655 unmodified lines
656656 return res;
657657 }
658658
659−int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa)
659+int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
660660 {
661661 struct inode *inode = d_inode(dentry);
662662 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
@@ -675,7 +675,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 12 unmodified lines
675675 }
676676
677677 int hfsplus_fileattr_set(struct mnt_idmap *idmap,
678− struct dentry *dentry, struct fileattr *fa)
678+ struct dentry *dentry, struct file_kattr *fa)
679679 {
680680 struct inode *inode = d_inode(dentry);
681681 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
fs/ioctl.c+0−309
@@ -453,315 +453,6 @@ out: · 452 unmodified lines
453453 return ret;
454454 }
455455
456−/**
457− * fileattr_fill_xflags - initialize fileattr with xflags
458− * @fa: fileattr pointer
459− * @xflags: FS_XFLAG_* flags
460− *
461− * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). All
462− * other fields are zeroed.
463− */
464−void fileattr_fill_xflags(struct fileattr *fa, u32 xflags)
465−{
466− memset(fa, 0, sizeof(*fa));
467− fa->fsx_valid = true;
468− fa->fsx_xflags = xflags;
469− if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE)
470− fa->flags |= FS_IMMUTABLE_FL;
471− if (fa->fsx_xflags & FS_XFLAG_APPEND)
472− fa->flags |= FS_APPEND_FL;
473− if (fa->fsx_xflags & FS_XFLAG_SYNC)
474− fa->flags |= FS_SYNC_FL;
475− if (fa->fsx_xflags & FS_XFLAG_NOATIME)
476− fa->flags |= FS_NOATIME_FL;
477− if (fa->fsx_xflags & FS_XFLAG_NODUMP)
478− fa->flags |= FS_NODUMP_FL;
479− if (fa->fsx_xflags & FS_XFLAG_DAX)
480− fa->flags |= FS_DAX_FL;
481− if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
482− fa->flags |= FS_PROJINHERIT_FL;
483−}
484−EXPORT_SYMBOL(fileattr_fill_xflags);
485−
486−/**
487− * fileattr_fill_flags - initialize fileattr with flags
488− * @fa: fileattr pointer
489− * @flags: FS_*_FL flags
490− *
491− * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags).
492− * All other fields are zeroed.
493− */
494−void fileattr_fill_flags(struct fileattr *fa, u32 flags)
495−{
496− memset(fa, 0, sizeof(*fa));
497− fa->flags_valid = true;
498− fa->flags = flags;
499− if (fa->flags & FS_SYNC_FL)
500− fa->fsx_xflags |= FS_XFLAG_SYNC;
501− if (fa->flags & FS_IMMUTABLE_FL)
502− fa->fsx_xflags |= FS_XFLAG_IMMUTABLE;
503− if (fa->flags & FS_APPEND_FL)
504− fa->fsx_xflags |= FS_XFLAG_APPEND;
505− if (fa->flags & FS_NODUMP_FL)
506− fa->fsx_xflags |= FS_XFLAG_NODUMP;
507− if (fa->flags & FS_NOATIME_FL)
508− fa->fsx_xflags |= FS_XFLAG_NOATIME;
509− if (fa->flags & FS_DAX_FL)
510− fa->fsx_xflags |= FS_XFLAG_DAX;
511− if (fa->flags & FS_PROJINHERIT_FL)
512− fa->fsx_xflags |= FS_XFLAG_PROJINHERIT;
513−}
514−EXPORT_SYMBOL(fileattr_fill_flags);
515−
516−/**
517− * vfs_fileattr_get - retrieve miscellaneous file attributes
518− * @dentry: the object to retrieve from
519− * @fa: fileattr pointer
520− *
521− * Call i_op->fileattr_get() callback, if exists.
522− *
523− * Return: 0 on success, or a negative error on failure.
524− */
525−int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
526−{
527− struct inode *inode = d_inode(dentry);
528−
529− if (!inode->i_op->fileattr_get)
530− return -ENOIOCTLCMD;
531−
532− return inode->i_op->fileattr_get(dentry, fa);
533−}
534−EXPORT_SYMBOL(vfs_fileattr_get);
535−
536−/**
537− * copy_fsxattr_to_user - copy fsxattr to userspace.
538− * @fa: fileattr pointer
539− * @ufa: fsxattr user pointer
540− *
541− * Return: 0 on success, or -EFAULT on failure.
542− */
543−int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa)
544−{
545− struct fsxattr xfa;
546−
547− memset(&xfa, 0, sizeof(xfa));
548− xfa.fsx_xflags = fa->fsx_xflags;
549− xfa.fsx_extsize = fa->fsx_extsize;
550− xfa.fsx_nextents = fa->fsx_nextents;
551− xfa.fsx_projid = fa->fsx_projid;
552− xfa.fsx_cowextsize = fa->fsx_cowextsize;
553−
554− if (copy_to_user(ufa, &xfa, sizeof(xfa)))
555− return -EFAULT;
556−
557− return 0;
558−}
559−EXPORT_SYMBOL(copy_fsxattr_to_user);
560−
561−static int copy_fsxattr_from_user(struct fileattr *fa,
562− struct fsxattr __user *ufa)
563−{
564− struct fsxattr xfa;
565−
566− if (copy_from_user(&xfa, ufa, sizeof(xfa)))
567− return -EFAULT;
568−
569− fileattr_fill_xflags(fa, xfa.fsx_xflags);
570− fa->fsx_extsize = xfa.fsx_extsize;
571− fa->fsx_nextents = xfa.fsx_nextents;
572− fa->fsx_projid = xfa.fsx_projid;
573− fa->fsx_cowextsize = xfa.fsx_cowextsize;
574−
575− return 0;
576−}
577−
578−/*
579− * Generic function to check FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS values and reject
580− * any invalid configurations.
581− *
582− * Note: must be called with inode lock held.
583− */
584−static int fileattr_set_prepare(struct inode *inode,
585− const struct fileattr *old_ma,
586− struct fileattr *fa)
587−{
588− int err;
589−
590− /*
591− * The IMMUTABLE and APPEND_ONLY flags can only be changed by
592− * the relevant capability.
593− */
594− if ((fa->flags ^ old_ma->flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
595− !capable(CAP_LINUX_IMMUTABLE))
596− return -EPERM;
597−
598− err = fscrypt_prepare_setflags(inode, old_ma->flags, fa->flags);
599− if (err)
600− return err;
601−
602− /*
603− * Project Quota ID state is only allowed to change from within the init
604− * namespace. Enforce that restriction only if we are trying to change
605− * the quota ID state. Everything else is allowed in user namespaces.
606− */
607− if (current_user_ns() != &init_user_ns) {
608− if (old_ma->fsx_projid != fa->fsx_projid)
609− return -EINVAL;
610− if ((old_ma->fsx_xflags ^ fa->fsx_xflags) &
611− FS_XFLAG_PROJINHERIT)
612− return -EINVAL;
613− } else {
614− /*
615− * Caller is allowed to change the project ID. If it is being
616− * changed, make sure that the new value is valid.
617− */
618− if (old_ma->fsx_projid != fa->fsx_projid &&
619− !projid_valid(make_kprojid(&init_user_ns, fa->fsx_projid)))
620− return -EINVAL;
621− }
622−
623− /* Check extent size hints. */
624− if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(inode->i_mode))
625− return -EINVAL;
626−
627− if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) &&
628− !S_ISDIR(inode->i_mode))
629− return -EINVAL;
630−
631− if ((fa->fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
632− !S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
633− return -EINVAL;
634−
635− /*
636− * It is only valid to set the DAX flag on regular files and
637− * directories on filesystems.
638− */
639− if ((fa->fsx_xflags & FS_XFLAG_DAX) &&
640− !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
641− return -EINVAL;
642−
643− /* Extent size hints of zero turn off the flags. */
644− if (fa->fsx_extsize == 0)
645− fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT);
646− if (fa->fsx_cowextsize == 0)
647− fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE;
648−
649− return 0;
650−}
651−
652−/**
653− * vfs_fileattr_set - change miscellaneous file attributes
654− * @idmap: idmap of the mount
655− * @dentry: the object to change
656− * @fa: fileattr pointer
657− *
658− * After verifying permissions, call i_op->fileattr_set() callback, if
659− * exists.
660− *
661− * Verifying attributes involves retrieving current attributes with
662− * i_op->fileattr_get(), this also allows initializing attributes that have
663− * not been set by the caller to current values. Inode lock is held
664− * thoughout to prevent racing with another instance.
665− *
666− * Return: 0 on success, or a negative error on failure.
667− */
668−int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
669− struct fileattr *fa)
670−{
671− struct inode *inode = d_inode(dentry);
672− struct fileattr old_ma = {};
673− int err;
674−
675− if (!inode->i_op->fileattr_set)
676− return -ENOIOCTLCMD;
677−
678− if (!inode_owner_or_capable(idmap, inode))
679− return -EPERM;
680−
681− inode_lock(inode);
682− err = vfs_fileattr_get(dentry, &old_ma);
683− if (!err) {
684− /* initialize missing bits from old_ma */
685− if (fa->flags_valid) {
686− fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON;
687− fa->fsx_extsize = old_ma.fsx_extsize;
688− fa->fsx_nextents = old_ma.fsx_nextents;
689− fa->fsx_projid = old_ma.fsx_projid;
690− fa->fsx_cowextsize = old_ma.fsx_cowextsize;
691− } else {
692− fa->flags |= old_ma.flags & ~FS_COMMON_FL;
693− }
694− err = fileattr_set_prepare(inode, &old_ma, fa);
695− if (!err)
696− err = inode->i_op->fileattr_set(idmap, dentry, fa);
697− }
698− inode_unlock(inode);
699−
700− return err;
701−}
702−EXPORT_SYMBOL(vfs_fileattr_set);
703−
704−static int ioctl_getflags(struct file *file, unsigned int __user *argp)
705−{
706− struct fileattr fa = { .flags_valid = true }; /* hint only */
707− int err;
708−
709− err = vfs_fileattr_get(file->f_path.dentry, &fa);
710− if (!err)
711− err = put_user(fa.flags, argp);
712− return err;
713−}
714−
715−static int ioctl_setflags(struct file *file, unsigned int __user *argp)
716−{
717− struct mnt_idmap *idmap = file_mnt_idmap(file);
718− struct dentry *dentry = file->f_path.dentry;
719− struct fileattr fa;
720− unsigned int flags;
721− int err;
722−
723− err = get_user(flags, argp);
724− if (!err) {
725− err = mnt_want_write_file(file);
726− if (!err) {
727− fileattr_fill_flags(&fa, flags);
728− err = vfs_fileattr_set(idmap, dentry, &fa);
729− mnt_drop_write_file(file);
730− }
731− }
732− return err;
733−}
734−
735−static int ioctl_fsgetxattr(struct file *file, void __user *argp)
736−{
737− struct fileattr fa = { .fsx_valid = true }; /* hint only */
738− int err;
739−
740− err = vfs_fileattr_get(file->f_path.dentry, &fa);
741− if (!err)
742− err = copy_fsxattr_to_user(&fa, argp);
743−
744− return err;
745−}
746−
747−static int ioctl_fssetxattr(struct file *file, void __user *argp)
748−{
749− struct mnt_idmap *idmap = file_mnt_idmap(file);
750− struct dentry *dentry = file->f_path.dentry;
751− struct fileattr fa;
752− int err;
753−
754− err = copy_fsxattr_from_user(&fa, argp);
755− if (!err) {
756− err = mnt_want_write_file(file);
757− if (!err) {
758− err = vfs_fileattr_set(idmap, dentry, &fa);
759− mnt_drop_write_file(file);
760− }
761− }
762− return err;
763−}
764−
765456 static int ioctl_getfsuuid(struct file *file, void __user *argp)
766457 {
767458 struct super_block *sb = file_inode(file)->i_sb;
fs/jfs/ioctl.c+2−2
@@ -57,7 +57,7 @@ static long jfs_map_ext2(unsigned long flags, int from) · 56 unmodified lines
5757 return mapped;
5858 }
5959
60−int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
60+int jfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
6161 {
6262 struct jfs_inode_info *jfs_inode = JFS_IP(d_inode(dentry));
6363 unsigned int flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
@@ -71,7 +71,7 @@ int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 7 unmodified lines
7171 }
7272
7373 int jfs_fileattr_set(struct mnt_idmap *idmap,
74− struct dentry *dentry, struct fileattr *fa)
74+ struct dentry *dentry, struct file_kattr *fa)
7575 {
7676 struct inode *inode = d_inode(dentry);
7777 struct jfs_inode_info *jfs_inode = JFS_IP(inode);
fs/jfs/jfs_inode.h+2−2
@@ -9,9 +9,9 @@ struct fid; · 8 unmodified lines
99
1010 extern struct inode *ialloc(struct inode *, umode_t);
1111 extern int jfs_fsync(struct file *, loff_t, loff_t, int);
12−extern int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
12+extern int jfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
1313 extern int jfs_fileattr_set(struct mnt_idmap *idmap,
14− struct dentry *dentry, struct fileattr *fa);
14+ struct dentry *dentry, struct file_kattr *fa);
1515 extern long jfs_ioctl(struct file *, unsigned int, unsigned long);
1616 extern struct inode *jfs_iget(struct super_block *, unsigned long);
1717 extern int jfs_commit_inode(struct inode *, int);
fs/nilfs2/ioctl.c+2−2
@@ -118,7 +118,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, · 117 unmodified lines
118118 *
119119 * Return: always 0 as success.
120120 */
121−int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
121+int nilfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
122122 {
123123 struct inode *inode = d_inode(dentry);
124124
@@ -136,7 +136,7 @@ int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 11 unmodified lines
136136 * Return: 0 on success, or a negative error code on failure.
137137 */
138138 int nilfs_fileattr_set(struct mnt_idmap *idmap,
139− struct dentry *dentry, struct fileattr *fa)
139+ struct dentry *dentry, struct file_kattr *fa)
140140 {
141141 struct inode *inode = d_inode(dentry);
142142 struct nilfs_transaction_info ti;
fs/nilfs2/nilfs.h+2−2
@@ -268,9 +268,9 @@ int nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, · 267 unmodified lines
268268 extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
269269
270270 /* ioctl.c */
271−int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *m);
271+int nilfs_fileattr_get(struct dentry *dentry, struct file_kattr *m);
272272 int nilfs_fileattr_set(struct mnt_idmap *idmap,
273− struct dentry *dentry, struct fileattr *fa);
273+ struct dentry *dentry, struct file_kattr *fa);
274274 long nilfs_ioctl(struct file *, unsigned int, unsigned long);
275275 long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
276276 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
fs/ocfs2/ioctl.c+2−2
@@ -62,7 +62,7 @@ static inline int o2info_coherent(struct ocfs2_info_request *req) · 61 unmodified lines
6262 return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));
6363 }
6464
65−int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa)
65+int ocfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
6666 {
6767 struct inode *inode = d_inode(dentry);
6868 unsigned int flags;
@@ -83,7 +83,7 @@ int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 14 unmodified lines
8383 }
8484
8585 int ocfs2_fileattr_set(struct mnt_idmap *idmap,
86− struct dentry *dentry, struct fileattr *fa)
86+ struct dentry *dentry, struct file_kattr *fa)
8787 {
8888 struct inode *inode = d_inode(dentry);
8989 unsigned int flags = fa->flags;
fs/ocfs2/ioctl.h+2−2
@@ -11,9 +11,9 @@ · 10 unmodified lines
1111 #ifndef OCFS2_IOCTL_PROTO_H
1212 #define OCFS2_IOCTL_PROTO_H
1313
14−int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);
14+int ocfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
1515 int ocfs2_fileattr_set(struct mnt_idmap *idmap,
16− struct dentry *dentry, struct fileattr *fa);
16+ struct dentry *dentry, struct file_kattr *fa);
1717 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
1818 long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
1919
fs/orangefs/inode.c+2−2
@@ -889,7 +889,7 @@ int orangefs_update_time(struct inode *inode, int flags) · 888 unmodified lines
889889 return __orangefs_setattr(inode, &iattr);
890890 }
891891
892−static int orangefs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
892+static int orangefs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
893893 {
894894 u64 val = 0;
895895 int ret;
@@ -910,7 +910,7 @@ static int orangefs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 14 unmodified lines
910910 }
911911
912912 static int orangefs_fileattr_set(struct mnt_idmap *idmap,
913− struct dentry *dentry, struct fileattr *fa)
913+ struct dentry *dentry, struct file_kattr *fa)
914914 {
915915 u64 val = 0;
916916
fs/overlayfs/copy_up.c+3−3
@@ -171,14 +171,14 @@ out: · 170 unmodified lines
171171 static int ovl_copy_fileattr(struct inode *inode, const struct path *old,
172172 const struct path *new)
173173 {
174− struct fileattr oldfa = { .flags_valid = true };
175− struct fileattr newfa = { .flags_valid = true };
174+ struct file_kattr oldfa = { .flags_valid = true };
175+ struct file_kattr newfa = { .flags_valid = true };
176176 int err;
177177
178178 err = ovl_real_fileattr_get(old, &oldfa);
179179 if (err) {
180180 /* Ntfs-3g returns -EINVAL for "no fileattr support" */
181− if (err == -ENOTTY || err == -EINVAL)
181+ if (err == -EOPNOTSUPP || err == -EINVAL)
182182 return 0;
183183 pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n",
184184 old->dentry, err);
fs/overlayfs/inode.c+7−10
@@ -610,7 +610,7 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, · 609 unmodified lines
610610 * Introducing security_inode_fileattr_get/set() hooks would solve this issue
611611 * properly.
612612 */
613−static int ovl_security_fileattr(const struct path *realpath, struct fileattr *fa,
613+static int ovl_security_fileattr(const struct path *realpath, struct file_kattr *fa,
614614 bool set)
615615 {
616616 struct file *file;
@@ -637,7 +637,7 @@ static int ovl_security_fileattr(const struct path *realpath, struct fileattr *f · 20 unmodified lines
637637 return err;
638638 }
639639
640−int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa)
640+int ovl_real_fileattr_set(const struct path *realpath, struct file_kattr *fa)
641641 {
642642 int err;
643643
@@ -649,7 +649,7 @@ int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa) · 5 unmodified lines
649649 }
650650
651651 int ovl_fileattr_set(struct mnt_idmap *idmap,
652− struct dentry *dentry, struct fileattr *fa)
652+ struct dentry *dentry, struct file_kattr *fa)
653653 {
654654 struct inode *inode = d_inode(dentry);
655655 struct path upperpath;
@@ -697,7 +697,7 @@ out: · 41 unmodified lines
697697 }
698698
699699 /* Convert inode protection flags to fileattr flags */
700−static void ovl_fileattr_prot_flags(struct inode *inode, struct fileattr *fa)
700+static void ovl_fileattr_prot_flags(struct inode *inode, struct file_kattr *fa)
701701 {
702702 BUILD_BUG_ON(OVL_PROT_FS_FLAGS_MASK & ~FS_COMMON_FL);
703703 BUILD_BUG_ON(OVL_PROT_FSX_FLAGS_MASK & ~FS_XFLAG_COMMON);
@@ -712,7 +712,7 @@ static void ovl_fileattr_prot_flags(struct inode *inode, struct fileattr *fa) · 8 unmodified lines
712712 }
713713 }
714714
715−int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa)
715+int ovl_real_fileattr_get(const struct path *realpath, struct file_kattr *fa)
716716 {
717717 int err;
718718
@@ -720,13 +720,10 @@ int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa) · 1 unmodified line
720720 if (err)
721721 return err;
722722
723− err = vfs_fileattr_get(realpath->dentry, fa);
724− if (err == -ENOIOCTLCMD)
725− err = -ENOTTY;
726− return err;
723+ return vfs_fileattr_get(realpath->dentry, fa);
727724 }
728725
729−int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)
726+int ovl_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
730727 {
731728 struct inode *inode = d_inode(dentry);
732729 struct path realpath;
fs/overlayfs/overlayfs.h+5−5
@@ -838,7 +838,7 @@ void ovl_copyattr(struct inode *to); · 837 unmodified lines
838838
839839 void ovl_check_protattr(struct inode *inode, struct dentry *upper);
840840 int ovl_set_protattr(struct inode *inode, struct dentry *upper,
841− struct fileattr *fa);
841+ struct file_kattr *fa);
842842
843843 static inline void ovl_copyflags(struct inode *from, struct inode *to)
844844 {
@@ -870,11 +870,11 @@ struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir, · 25 unmodified lines
870870
871871 /* file.c */
872872 extern const struct file_operations ovl_file_operations;
873−int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa);
874−int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa);
875−int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa);
873+int ovl_real_fileattr_get(const struct path *realpath, struct file_kattr *fa);
874+int ovl_real_fileattr_set(const struct path *realpath, struct file_kattr *fa);
875+int ovl_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
876876 int ovl_fileattr_set(struct mnt_idmap *idmap,
877− struct dentry *dentry, struct fileattr *fa);
877+ struct dentry *dentry, struct file_kattr *fa);
878878 struct ovl_file;
879879 struct ovl_file *ovl_file_alloc(struct file *realfile);
880880 void ovl_file_free(struct ovl_file *of);
fs/overlayfs/util.c+1−1
@@ -966,7 +966,7 @@ void ovl_check_protattr(struct inode *inode, struct dentry *upper) · 965 unmodified lines
966966 }
967967
968968 int ovl_set_protattr(struct inode *inode, struct dentry *upper,
969− struct fileattr *fa)
969+ struct file_kattr *fa)
970970 {
971971 struct ovl_fs *ofs = OVL_FS(inode->i_sb);
972972 char buf[OVL_PROTATTR_MAX];
fs/ubifs/ioctl.c+2−2
@@ -130,7 +130,7 @@ static int setflags(struct inode *inode, int flags) · 129 unmodified lines
130130 return err;
131131 }
132132
133−int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
133+int ubifs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
134134 {
135135 struct inode *inode = d_inode(dentry);
136136 int flags = ubifs2ioctl(ubifs_inode(inode)->flags);
@@ -145,7 +145,7 @@ int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 8 unmodified lines
145145 }
146146
147147 int ubifs_fileattr_set(struct mnt_idmap *idmap,
148− struct dentry *dentry, struct fileattr *fa)
148+ struct dentry *dentry, struct file_kattr *fa)
149149 {
150150 struct inode *inode = d_inode(dentry);
151151 int flags = fa->flags;
fs/ubifs/ubifs.h+2−2
@@ -2073,9 +2073,9 @@ int ubifs_recover_size(struct ubifs_info *c, bool in_place); · 2072 unmodified lines
20732073 void ubifs_destroy_size_tree(struct ubifs_info *c);
20742074
20752075 /* ioctl.c */
2076−int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
2076+int ubifs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
20772077 int ubifs_fileattr_set(struct mnt_idmap *idmap,
2078− struct dentry *dentry, struct fileattr *fa);
2078+ struct dentry *dentry, struct file_kattr *fa);
20792079 long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
20802080 void ubifs_set_inode_flags(struct inode *inode);
20812081 #ifdef CONFIG_COMPAT
fs/xfs/xfs_ioctl.c+9−9
@@ -444,7 +444,7 @@ static void · 443 unmodified lines
444444 xfs_fill_fsxattr(
445445 struct xfs_inode *ip,
446446 int whichfork,
447− struct fileattr *fa)
447+ struct file_kattr *fa)
448448 {
449449 struct xfs_mount *mp = ip->i_mount;
450450 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
@@ -496,7 +496,7 @@ xfs_ioc_fsgetxattra( · 45 unmodified lines
496496 xfs_inode_t *ip,
497497 void __user *arg)
498498 {
499− struct fileattr fa;
499+ struct file_kattr fa;
500500
501501 xfs_ilock(ip, XFS_ILOCK_SHARED);
502502 xfs_fill_fsxattr(ip, XFS_ATTR_FORK, &fa);
@@ -508,7 +508,7 @@ xfs_ioc_fsgetxattra( · 5 unmodified lines
508508 int
509509 xfs_fileattr_get(
510510 struct dentry *dentry,
511− struct fileattr *fa)
511+ struct file_kattr *fa)
512512 {
513513 struct xfs_inode *ip = XFS_I(d_inode(dentry));
514514
@@ -526,7 +526,7 @@ static int · 11 unmodified lines
526526 xfs_ioctl_setattr_xflags(
527527 struct xfs_trans *tp,
528528 struct xfs_inode *ip,
529− struct fileattr *fa)
529+ struct file_kattr *fa)
530530 {
531531 struct xfs_mount *mp = ip->i_mount;
532532 bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);
@@ -582,7 +582,7 @@ xfs_ioctl_setattr_xflags( · 49 unmodified lines
582582 static void
583583 xfs_ioctl_setattr_prepare_dax(
584584 struct xfs_inode *ip,
585− struct fileattr *fa)
585+ struct file_kattr *fa)
586586 {
587587 struct xfs_mount *mp = ip->i_mount;
588588 struct inode *inode = VFS_I(ip);
@@ -642,7 +642,7 @@ out_error: · 53 unmodified lines
642642 static int
643643 xfs_ioctl_setattr_check_extsize(
644644 struct xfs_inode *ip,
645− struct fileattr *fa)
645+ struct file_kattr *fa)
646646 {
647647 struct xfs_mount *mp = ip->i_mount;
648648 xfs_failaddr_t failaddr;
@@ -684,7 +684,7 @@ xfs_ioctl_setattr_check_extsize( · 35 unmodified lines
684684 static int
685685 xfs_ioctl_setattr_check_cowextsize(
686686 struct xfs_inode *ip,
687− struct fileattr *fa)
687+ struct file_kattr *fa)
688688 {
689689 struct xfs_mount *mp = ip->i_mount;
690690 xfs_failaddr_t failaddr;
@@ -709,7 +709,7 @@ xfs_ioctl_setattr_check_cowextsize( · 18 unmodified lines
709709 static int
710710 xfs_ioctl_setattr_check_projid(
711711 struct xfs_inode *ip,
712− struct fileattr *fa)
712+ struct file_kattr *fa)
713713 {
714714 if (!fa->fsx_valid)
715715 return 0;
@@ -725,7 +725,7 @@ int · 9 unmodified lines
725725 xfs_fileattr_set(
726726 struct mnt_idmap *idmap,
727727 struct dentry *dentry,
728− struct fileattr *fa)
728+ struct file_kattr *fa)
729729 {
730730 struct xfs_inode *ip = XFS_I(d_inode(dentry));
731731 struct xfs_mount *mp = ip->i_mount;
fs/xfs/xfs_ioctl.h+2−2
@@ -17,13 +17,13 @@ xfs_ioc_swapext( · 16 unmodified lines
1717 extern int
1818 xfs_fileattr_get(
1919 struct dentry *dentry,
20− struct fileattr *fa);
20+ struct file_kattr *fa);
2121
2222 extern int
2323 xfs_fileattr_set(
2424 struct mnt_idmap *idmap,
2525 struct dentry *dentry,
26− struct fileattr *fa);
26+ struct file_kattr *fa);
2727
2828 extern long
2929 xfs_file_ioctl(
include/linux/fileattr.h+31−7
@@ -14,13 +14,33 @@ · 13 unmodified lines
1414 FS_XFLAG_NODUMP | FS_XFLAG_NOATIME | FS_XFLAG_DAX | \
1515 FS_XFLAG_PROJINHERIT)
1616
17+/* Read-only inode flags */
18+#define FS_XFLAG_RDONLY_MASK \
19+ (FS_XFLAG_PREALLOC | FS_XFLAG_HASATTR)
20+
21+/* Flags to indicate valid value of fsx_ fields */
22+#define FS_XFLAG_VALUES_MASK \
23+ (FS_XFLAG_EXTSIZE | FS_XFLAG_COWEXTSIZE)
24+
25+/* Flags for directories */
26+#define FS_XFLAG_DIRONLY_MASK \
27+ (FS_XFLAG_RTINHERIT | FS_XFLAG_NOSYMLINKS | FS_XFLAG_EXTSZINHERIT)
28+
29+/* Misc settable flags */
30+#define FS_XFLAG_MISC_MASK \
31+ (FS_XFLAG_REALTIME | FS_XFLAG_NODEFRAG | FS_XFLAG_FILESTREAM)
32+
33+#define FS_XFLAGS_MASK \
34+ (FS_XFLAG_COMMON | FS_XFLAG_RDONLY_MASK | FS_XFLAG_VALUES_MASK | \
35+ FS_XFLAG_DIRONLY_MASK | FS_XFLAG_MISC_MASK)
36+
1737 /*
1838 * Merged interface for miscellaneous file attributes. 'flags' originates from
1939 * ext* and 'fsx_flags' from xfs. There's some overlap between the two, which
2040 * is handled by the VFS helpers, so filesystems are free to implement just one
2141 * or both of these sub-interfaces.
2242 */
23−struct fileattr {
43+struct file_kattr {
2444 u32 flags; /* flags (FS_IOC_GETFLAGS/FS_IOC_SETFLAGS) */
2545 /* struct fsxattr: */
2646 u32 fsx_xflags; /* xflags field value (get/set) */
@@ -33,10 +53,10 @@ struct fileattr { · 6 unmodified lines
3353 bool fsx_valid:1;
3454 };
3555
36−int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa);
56+int copy_fsxattr_to_user(const struct file_kattr *fa, struct fsxattr __user *ufa);
3757
38−void fileattr_fill_xflags(struct fileattr *fa, u32 xflags);
39−void fileattr_fill_flags(struct fileattr *fa, u32 flags);
58+void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags);
59+void fileattr_fill_flags(struct file_kattr *fa, u32 flags);
4060
4161 /**
4262 * fileattr_has_fsx - check for extended flags/attributes
@@ -45,15 +65,19 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flags); · 2 unmodified lines
4565 * Return: true if any attributes are present that are not represented in
4666 * ->flags.
4767 */
48−static inline bool fileattr_has_fsx(const struct fileattr *fa)
68+static inline bool fileattr_has_fsx(const struct file_kattr *fa)
4969 {
5070 return fa->fsx_valid &&
5171 ((fa->fsx_xflags & ~FS_XFLAG_COMMON) || fa->fsx_extsize != 0 ||
5272 fa->fsx_projid != 0 || fa->fsx_cowextsize != 0);
5373 }
5474
55−int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
75+int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
5676 int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
57− struct fileattr *fa);
77+ struct file_kattr *fa);
78+int ioctl_getflags(struct file *file, unsigned int __user *argp);
79+int ioctl_setflags(struct file *file, unsigned int __user *argp);
80+int ioctl_fsgetxattr(struct file *file, void __user *argp);
81+int ioctl_fssetxattr(struct file *file, void __user *argp);
5882
5983 #endif /* _LINUX_FILEATTR_H */
include/linux/fs.h+3−3
@@ -80,7 +80,7 @@ struct fsnotify_mark_connector; · 79 unmodified lines
8080 struct fsnotify_sb_info;
8181 struct fs_context;
8282 struct fs_parameter_spec;
83−struct fileattr;
83+struct file_kattr;
8484 struct iomap_ops;
8585
8686 extern void __init inode_init(void);
@@ -2257,8 +2257,8 @@ struct inode_operations { · 2170 unmodified lines
22572257 int (*set_acl)(struct mnt_idmap *, struct dentry *,
22582258 struct posix_acl *, int);
22592259 int (*fileattr_set)(struct mnt_idmap *idmap,
2260− struct dentry *dentry, struct fileattr *fa);
2261− int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);
2260+ struct dentry *dentry, struct file_kattr *fa);
2261+ int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa);
22622262 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
22632263 } ____cacheline_aligned;
22642264
include/linux/lsm_hook_defs.h+2−0
@@ -157,6 +157,8 @@ LSM_HOOK(int, 0, inode_removexattr, struct mnt_idmap *idmap, · 156 unmodified lines
157157 struct dentry *dentry, const char *name)
158158 LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry,
159159 const char *name)
160+LSM_HOOK(int, 0, inode_file_setattr, struct dentry *dentry, struct file_kattr *fa)
161+LSM_HOOK(int, 0, inode_file_getattr, struct dentry *dentry, struct file_kattr *fa)
160162 LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap,
161163 struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)
162164 LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry,
include/linux/security.h+16−0
@@ -451,6 +451,10 @@ int security_inode_listxattr(struct dentry *dentry); · 450 unmodified lines
451451 int security_inode_removexattr(struct mnt_idmap *idmap,
452452 struct dentry *dentry, const char *name);
453453 void security_inode_post_removexattr(struct dentry *dentry, const char *name);
454+int security_inode_file_setattr(struct dentry *dentry,
455+ struct file_kattr *fa);
456+int security_inode_file_getattr(struct dentry *dentry,
457+ struct file_kattr *fa);
454458 int security_inode_need_killpriv(struct dentry *dentry);
455459 int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry);
456460 int security_inode_getsecurity(struct mnt_idmap *idmap,
@@ -1052,6 +1056,18 @@ static inline void security_inode_post_removexattr(struct dentry *dentry, · 595 unmodified lines
10521056 const char *name)
10531057 { }
10541058
1059+static inline int security_inode_file_setattr(struct dentry *dentry,
1060+ struct file_kattr *fa)
1061+{
1062+ return 0;
1063+}
1064+
1065+static inline int security_inode_file_getattr(struct dentry *dentry,
1066+ struct file_kattr *fa)
1067+{
1068+ return 0;
1069+}
1070+
10551071 static inline int security_inode_need_killpriv(struct dentry *dentry)
10561072 {
10571073 return cap_inode_need_killpriv(dentry);
include/linux/syscalls.h+7−0
@@ -78,6 +78,7 @@ struct cachestat; · 77 unmodified lines
7878 struct statmount;
7979 struct mnt_id_req;
8080 struct xattr_args;
81+struct file_attr;
8182
8283 #include <linux/types.h>
8384 #include <linux/aio_abi.h>
@@ -371,6 +372,12 @@ asmlinkage long sys_removexattrat(int dfd, const char __user *path, · 287 unmodified lines
371372 asmlinkage long sys_lremovexattr(const char __user *path,
372373 const char __user *name);
373374 asmlinkage long sys_fremovexattr(int fd, const char __user *name);
375+asmlinkage long sys_file_getattr(int dfd, const char __user *filename,
376+ struct file_attr __user *attr, size_t usize,
377+ unsigned int at_flags);
378+asmlinkage long sys_file_setattr(int dfd, const char __user *filename,
379+ struct file_attr __user *attr, size_t usize,
380+ unsigned int at_flags);
374381 asmlinkage long sys_getcwd(char __user *buf, unsigned long size);
375382 asmlinkage long sys_eventfd2(unsigned int count, int flags);
376383 asmlinkage long sys_epoll_create1(int flags);
include/uapi/asm-generic/unistd.h+7−1
@@ -852,8 +852,14 @@ __SYSCALL(__NR_removexattrat, sys_removexattrat) · 851 unmodified lines
852852 #define __NR_open_tree_attr 467
853853 __SYSCALL(__NR_open_tree_attr, sys_open_tree_attr)
854854
855+/* fs/inode.c */
856+#define __NR_file_getattr 468
857+__SYSCALL(__NR_file_getattr, sys_file_getattr)
858+#define __NR_file_setattr 469
859+__SYSCALL(__NR_file_setattr, sys_file_setattr)
860+
855861 #undef __NR_syscalls
856−#define __NR_syscalls 468
862+#define __NR_syscalls 470
857863
858864 /*
859865 * 32 bit systems traditionally used different
include/uapi/linux/fs.h+18−0
@@ -216,6 +216,24 @@ struct fsxattr { · 215 unmodified lines
216216 unsigned char fsx_pad[8];
217217 };
218218
219+/*
220+ * Variable size structure for file_[sg]et_attr().
221+ *
222+ * Note. This is alternative to the structure 'struct file_kattr'/'struct fsxattr'.
223+ * As this structure is passed to/from userspace with its size, this can
224+ * be versioned based on the size.
225+ */
226+struct file_attr {
227+ __u64 fa_xflags; /* xflags field value (get/set) */
228+ __u32 fa_extsize; /* extsize field value (get/set)*/
229+ __u32 fa_nextents; /* nextents field value (get) */
230+ __u32 fa_projid; /* project identifier (get/set) */
231+ __u32 fa_cowextsize; /* CoW extsize field value (get/set) */
232+};
233+
234+#define FILE_ATTR_SIZE_VER0 24
235+#define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER0
236+
219237 /*
220238 * Flags for the fsx_xflags field
221239 */
mm/shmem.c+2−2
@@ -4187,7 +4187,7 @@ static const char *shmem_get_link(struct dentry *dentry, struct inode *inode, · 4186 unmodified lines
41874187
41884188 #ifdef CONFIG_TMPFS_XATTR
41894189
4190−static int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)
4190+static int shmem_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
41914191 {
41924192 struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
41934193
@@ -4197,7 +4197,7 @@ static int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 3 unmodified lines
41974197 }
41984198
41994199 static int shmem_fileattr_set(struct mnt_idmap *idmap,
4200− struct dentry *dentry, struct fileattr *fa)
4200+ struct dentry *dentry, struct file_kattr *fa)
42014201 {
42024202 struct inode *inode = d_inode(dentry);
42034203 struct shmem_inode_info *info = SHMEM_I(inode);
scripts/syscall.tbl+2−0
@@ -408,3 +408,5 @@ · 407 unmodified lines
408408 465 common listxattrat sys_listxattrat
409409 466 common removexattrat sys_removexattrat
410410 467 common open_tree_attr sys_open_tree_attr
411+468 common file_getattr sys_file_getattr
412+469 common file_setattr sys_file_setattr
security/security.c+30−0
@@ -2622,6 +2622,36 @@ void security_inode_post_removexattr(struct dentry *dentry, const char *name) · 2621 unmodified lines
26222622 call_void_hook(inode_post_removexattr, dentry, name);
26232623 }
26242624
2625+/**
2626+ * security_inode_file_setattr() - check if setting fsxattr is allowed
2627+ * @dentry: file to set filesystem extended attributes on
2628+ * @fa: extended attributes to set on the inode
2629+ *
2630+ * Called when file_setattr() syscall or FS_IOC_FSSETXATTR ioctl() is called on
2631+ * inode
2632+ *
2633+ * Return: Returns 0 if permission is granted.
2634+ */
2635+int security_inode_file_setattr(struct dentry *dentry, struct file_kattr *fa)
2636+{
2637+ return call_int_hook(inode_file_setattr, dentry, fa);
2638+}
2639+
2640+/**
2641+ * security_inode_file_getattr() - check if retrieving fsxattr is allowed
2642+ * @dentry: file to retrieve filesystem extended attributes from
2643+ * @fa: extended attributes to get
2644+ *
2645+ * Called when file_getattr() syscall or FS_IOC_FSGETXATTR ioctl() is called on
2646+ * inode
2647+ *
2648+ * Return: Returns 0 if permission is granted.
2649+ */
2650+int security_inode_file_getattr(struct dentry *dentry, struct file_kattr *fa)
2651+{
2652+ return call_int_hook(inode_file_getattr, dentry, fa);
2653+}
2654+
26252655 /**
26262656 * security_inode_need_killpriv() - Check if security_inode_killpriv() required
26272657 * @dentry: associated dentry
security/selinux/hooks.c+14−0
@@ -3480,6 +3480,18 @@ static int selinux_inode_removexattr(struct mnt_idmap *idmap, · 3479 unmodified lines
34803480 return -EACCES;
34813481 }
34823482
3483+static int selinux_inode_file_setattr(struct dentry *dentry,
3484+ struct file_kattr *fa)
3485+{
3486+ return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3487+}
3488+
3489+static int selinux_inode_file_getattr(struct dentry *dentry,
3490+ struct file_kattr *fa)
3491+{
3492+ return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
3493+}
3494+
34833495 static int selinux_path_notify(const struct path *path, u64 mask,
34843496 unsigned int obj_type)
34853497 {
@@ -7350,6 +7362,8 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { · 3864 unmodified lines
73507362 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
73517363 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
73527364 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
7365+ LSM_HOOK_INIT(inode_file_getattr, selinux_inode_file_getattr),
7366+ LSM_HOOK_INIT(inode_file_setattr, selinux_inode_file_setattr),
73537367 LSM_HOOK_INIT(inode_set_acl, selinux_inode_set_acl),
73547368 LSM_HOOK_INIT(inode_get_acl, selinux_inode_get_acl),
73557369 LSM_HOOK_INIT(inode_remove_acl, selinux_inode_remove_acl),