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
87 int (*tmpfile) (struct mnt_idmap *, struct inode *,87 int (*tmpfile) (struct mnt_idmap *, struct inode *,
88 struct file *, umode_t);88 struct file *, umode_t);
89 int (*fileattr_set)(struct mnt_idmap *idmap,89 int (*fileattr_set)(struct mnt_idmap *idmap,
90 struct dentry *dentry, struct fileattr *fa);90 struct dentry *dentry, struct file_kattr *fa);
91 int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);91 int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa);
92 struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int);92 struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int);
93 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);93 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
94 94
Documentation/filesystems/vfs.rst+2−2
@@ -515,8 +515,8 @@ As of kernel 2.6.22, the following members are defined: · 514 unmodified lines
515 struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int);515 struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int);
516 int (*set_acl)(struct mnt_idmap *, struct dentry *, struct posix_acl *, int);516 int (*set_acl)(struct mnt_idmap *, struct dentry *, struct posix_acl *, int);
517 int (*fileattr_set)(struct mnt_idmap *idmap,517 int (*fileattr_set)(struct mnt_idmap *idmap,
518 struct dentry *dentry, struct fileattr *fa);518 struct dentry *dentry, struct file_kattr *fa);
519 int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);519 int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa);
520 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);520 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
521 };521 };
522 522
arch/alpha/kernel/syscalls/syscall.tbl+2−0
@@ -507,3 +507,5 @@ · 506 unmodified lines
507575 common listxattrat sys_listxattrat507575 common listxattrat sys_listxattrat
508576 common removexattrat sys_removexattrat508576 common removexattrat sys_removexattrat
509577 common open_tree_attr sys_open_tree_attr509577 common open_tree_attr sys_open_tree_attr
510578 common file_getattr sys_file_getattr
511579 common file_setattr sys_file_setattr
arch/arm/tools/syscall.tbl+2−0
@@ -482,3 +482,5 @@ · 481 unmodified lines
482465 common listxattrat sys_listxattrat482465 common listxattrat sys_listxattrat
483466 common removexattrat sys_removexattrat483466 common removexattrat sys_removexattrat
484467 common open_tree_attr sys_open_tree_attr484467 common open_tree_attr sys_open_tree_attr
485468 common file_getattr sys_file_getattr
486469 common file_setattr sys_file_setattr
arch/arm64/tools/syscall_32.tbl+2−0
@@ -479,3 +479,5 @@ · 478 unmodified lines
479465 common listxattrat sys_listxattrat479465 common listxattrat sys_listxattrat
480466 common removexattrat sys_removexattrat480466 common removexattrat sys_removexattrat
481467 common open_tree_attr sys_open_tree_attr481467 common open_tree_attr sys_open_tree_attr
482468 common file_getattr sys_file_getattr
483469 common file_setattr sys_file_setattr
arch/m68k/kernel/syscalls/syscall.tbl+2−0
@@ -467,3 +467,5 @@ · 466 unmodified lines
467465 common listxattrat sys_listxattrat467465 common listxattrat sys_listxattrat
468466 common removexattrat sys_removexattrat468466 common removexattrat sys_removexattrat
469467 common open_tree_attr sys_open_tree_attr469467 common open_tree_attr sys_open_tree_attr
470468 common file_getattr sys_file_getattr
471469 common file_setattr sys_file_setattr
arch/microblaze/kernel/syscalls/syscall.tbl+2−0
@@ -473,3 +473,5 @@ · 472 unmodified lines
473465 common listxattrat sys_listxattrat473465 common listxattrat sys_listxattrat
474466 common removexattrat sys_removexattrat474466 common removexattrat sys_removexattrat
475467 common open_tree_attr sys_open_tree_attr475467 common open_tree_attr sys_open_tree_attr
476468 common file_getattr sys_file_getattr
477469 common file_setattr sys_file_setattr
arch/mips/kernel/syscalls/syscall_n32.tbl+2−0
@@ -406,3 +406,5 @@ · 405 unmodified lines
406465 n32 listxattrat sys_listxattrat406465 n32 listxattrat sys_listxattrat
407466 n32 removexattrat sys_removexattrat407466 n32 removexattrat sys_removexattrat
408467 n32 open_tree_attr sys_open_tree_attr408467 n32 open_tree_attr sys_open_tree_attr
409468 n32 file_getattr sys_file_getattr
410469 n32 file_setattr sys_file_setattr
arch/mips/kernel/syscalls/syscall_n64.tbl+2−0
@@ -382,3 +382,5 @@ · 381 unmodified lines
382465 n64 listxattrat sys_listxattrat382465 n64 listxattrat sys_listxattrat
383466 n64 removexattrat sys_removexattrat383466 n64 removexattrat sys_removexattrat
384467 n64 open_tree_attr sys_open_tree_attr384467 n64 open_tree_attr sys_open_tree_attr
385468 n64 file_getattr sys_file_getattr
386469 n64 file_setattr sys_file_setattr
arch/mips/kernel/syscalls/syscall_o32.tbl+2−0
@@ -455,3 +455,5 @@ · 454 unmodified lines
455465 o32 listxattrat sys_listxattrat455465 o32 listxattrat sys_listxattrat
456466 o32 removexattrat sys_removexattrat456466 o32 removexattrat sys_removexattrat
457467 o32 open_tree_attr sys_open_tree_attr457467 o32 open_tree_attr sys_open_tree_attr
458468 o32 file_getattr sys_file_getattr
459469 o32 file_setattr sys_file_setattr
arch/parisc/kernel/syscalls/syscall.tbl+2−0
@@ -466,3 +466,5 @@ · 465 unmodified lines
466465 common listxattrat sys_listxattrat466465 common listxattrat sys_listxattrat
467466 common removexattrat sys_removexattrat467466 common removexattrat sys_removexattrat
468467 common open_tree_attr sys_open_tree_attr468467 common open_tree_attr sys_open_tree_attr
469468 common file_getattr sys_file_getattr
470469 common file_setattr sys_file_setattr
arch/powerpc/kernel/syscalls/syscall.tbl+2−0
@@ -558,3 +558,5 @@ · 557 unmodified lines
558465 common listxattrat sys_listxattrat558465 common listxattrat sys_listxattrat
559466 common removexattrat sys_removexattrat559466 common removexattrat sys_removexattrat
560467 common open_tree_attr sys_open_tree_attr560467 common open_tree_attr sys_open_tree_attr
561468 common file_getattr sys_file_getattr
562469 common file_setattr sys_file_setattr
arch/s390/kernel/syscalls/syscall.tbl+2−0
@@ -470,3 +470,5 @@ · 469 unmodified lines
470465 common listxattrat sys_listxattrat sys_listxattrat470465 common listxattrat sys_listxattrat sys_listxattrat
471466 common removexattrat sys_removexattrat sys_removexattrat471466 common removexattrat sys_removexattrat sys_removexattrat
472467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr472467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr
473468 common file_getattr sys_file_getattr sys_file_getattr
474469 common file_setattr sys_file_setattr sys_file_setattr
arch/sh/kernel/syscalls/syscall.tbl+2−0
@@ -471,3 +471,5 @@ · 470 unmodified lines
471465 common listxattrat sys_listxattrat471465 common listxattrat sys_listxattrat
472466 common removexattrat sys_removexattrat472466 common removexattrat sys_removexattrat
473467 common open_tree_attr sys_open_tree_attr473467 common open_tree_attr sys_open_tree_attr
474468 common file_getattr sys_file_getattr
475469 common file_setattr sys_file_setattr
arch/sparc/kernel/syscalls/syscall.tbl+2−0
@@ -513,3 +513,5 @@ · 512 unmodified lines
513465 common listxattrat sys_listxattrat513465 common listxattrat sys_listxattrat
514466 common removexattrat sys_removexattrat514466 common removexattrat sys_removexattrat
515467 common open_tree_attr sys_open_tree_attr515467 common open_tree_attr sys_open_tree_attr
516468 common file_getattr sys_file_getattr
517469 common file_setattr sys_file_setattr
arch/x86/entry/syscalls/syscall_32.tbl+2−0
@@ -473,3 +473,5 @@ · 472 unmodified lines
473465 i386 listxattrat sys_listxattrat473465 i386 listxattrat sys_listxattrat
474466 i386 removexattrat sys_removexattrat474466 i386 removexattrat sys_removexattrat
475467 i386 open_tree_attr sys_open_tree_attr475467 i386 open_tree_attr sys_open_tree_attr
476468 i386 file_getattr sys_file_getattr
477469 i386 file_setattr sys_file_setattr
arch/x86/entry/syscalls/syscall_64.tbl+2−0
@@ -391,6 +391,8 @@ · 390 unmodified lines
391465 common listxattrat sys_listxattrat391465 common listxattrat sys_listxattrat
392466 common removexattrat sys_removexattrat392466 common removexattrat sys_removexattrat
393467 common open_tree_attr sys_open_tree_attr393467 common open_tree_attr sys_open_tree_attr
394468 common file_getattr sys_file_getattr
395469 common file_setattr sys_file_setattr
394 396
395#397#
396# Due to a historical design error, certain syscalls are numbered differently398# 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
438465 common listxattrat sys_listxattrat438465 common listxattrat sys_listxattrat
439466 common removexattrat sys_removexattrat439466 common removexattrat sys_removexattrat
440467 common open_tree_attr sys_open_tree_attr440467 common open_tree_attr sys_open_tree_attr
441468 common file_getattr sys_file_getattr
442469 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
15 pnode.o splice.o sync.o utimes.o d_path.o \15 pnode.o splice.o sync.o utimes.o d_path.o \
16 stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \16 stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
17 fs_types.o fs_context.o fs_parser.o fsopen.o init.o \17 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.o18 kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o \
19 file_attr.o
19 20
20obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o21obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o
21obj-$(CONFIG_PROC_FS) += proc_namespace.o22obj-$(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
1617};1617};
1618 1618
1619static int bch2_fileattr_get(struct dentry *dentry,1619static int bch2_fileattr_get(struct dentry *dentry,
1620 struct fileattr *fa)1620 struct file_kattr *fa)
1621{1621{
1622 struct bch_inode_info *inode = to_bch_ei(d_inode(dentry));1622 struct bch_inode_info *inode = to_bch_ei(d_inode(dentry));
1623 struct bch_fs *c = inode->v.i_sb->s_fs_info;1623 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
1680 1680
1681static int bch2_fileattr_set(struct mnt_idmap *idmap,1681static int bch2_fileattr_set(struct mnt_idmap *idmap,
1682 struct dentry *dentry,1682 struct dentry *dentry,
1683 struct fileattr *fa)1683 struct file_kattr *fa)
1684{1684{
1685 struct bch_inode_info *inode = to_bch_ei(d_inode(dentry));1685 struct bch_inode_info *inode = to_bch_ei(d_inode(dentry));
1686 struct bch_fs *c = inode->v.i_sb->s_fs_info;1686 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
245 * Set flags/xflags from the internal inode flags. The remaining items of245 * Set flags/xflags from the internal inode flags. The remaining items of
246 * fsxattr are zeroed.246 * fsxattr are zeroed.
247 */247 */
248int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)248int btrfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
249{249{
250 const struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));250 const struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
251 251
@@ -254,7 +254,7 @@ int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 2 unmodified lines
254}254}
255 255
256int btrfs_fileattr_set(struct mnt_idmap *idmap,256int btrfs_fileattr_set(struct mnt_idmap *idmap,
257 struct dentry *dentry, struct fileattr *fa)257 struct dentry *dentry, struct file_kattr *fa)
258{258{
259 struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));259 struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
260 struct btrfs_root *root = inode->root;260 struct btrfs_root *root = inode->root;
fs/btrfs/ioctl.h+3−3
@@ -8,7 +8,7 @@ · 7 unmodified lines
8struct file;8struct file;
9struct dentry;9struct dentry;
10struct mnt_idmap;10struct mnt_idmap;
11struct fileattr;11struct file_kattr;
12struct io_uring_cmd;12struct io_uring_cmd;
13struct btrfs_inode;13struct btrfs_inode;
14struct btrfs_fs_info;14struct btrfs_fs_info;
@@ -16,9 +16,9 @@ struct btrfs_ioctl_balance_args; · 1 unmodified line
16 16
17long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);17long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
18long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);18long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
19int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);19int btrfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
20int btrfs_fileattr_set(struct mnt_idmap *idmap,20int btrfs_fileattr_set(struct mnt_idmap *idmap,
21 struct dentry *dentry, struct fileattr *fa);21 struct dentry *dentry, struct file_kattr *fa);
22int btrfs_ioctl_get_supported_features(void __user *arg);22int btrfs_ioctl_get_supported_features(void __user *arg);
23void btrfs_sync_inode_flags_to_i_flags(struct btrfs_inode *inode);23void btrfs_sync_inode_flags_to_i_flags(struct btrfs_inode *inode);
24void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info,24void 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
1124 return rc;1124 return rc;
1125}1125}
1126 1126
1127static int ecryptfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)1127static int ecryptfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
1128{1128{
1129 return vfs_fileattr_get(ecryptfs_dentry_to_lower(dentry), fa);1129 return vfs_fileattr_get(ecryptfs_dentry_to_lower(dentry), fa);
1130}1130}
1131 1131
1132static int ecryptfs_fileattr_set(struct mnt_idmap *idmap,1132static int ecryptfs_fileattr_set(struct mnt_idmap *idmap,
1133 struct dentry *dentry, struct fileattr *fa)1133 struct dentry *dentry, struct file_kattr *fa)
1134{1134{
1135 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);1135 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
1136 int rc;1136 int rc;
fs/efivarfs/inode.c+2−2
@@ -138,7 +138,7 @@ const struct inode_operations efivarfs_dir_inode_operations = { · 137 unmodified lines
138};138};
139 139
140static int140static int
141efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)141efivarfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
142{142{
143 unsigned int i_flags;143 unsigned int i_flags;
144 unsigned int flags = 0;144 unsigned int flags = 0;
@@ -154,7 +154,7 @@ efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 9 unmodified lines
154 154
155static int155static int
156efivarfs_fileattr_set(struct mnt_idmap *idmap,156efivarfs_fileattr_set(struct mnt_idmap *idmap,
157 struct dentry *dentry, struct fileattr *fa)157 struct dentry *dentry, struct file_kattr *fa)
158{158{
159 unsigned int i_flags = 0;159 unsigned int i_flags = 0;
160 160
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
750 u64 start, u64 len);750 u64 start, u64 len);
751 751
752/* ioctl.c */752/* ioctl.c */
753extern int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa);753extern int ext2_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
754extern int ext2_fileattr_set(struct mnt_idmap *idmap,754extern int ext2_fileattr_set(struct mnt_idmap *idmap,
755 struct dentry *dentry, struct fileattr *fa);755 struct dentry *dentry, struct file_kattr *fa);
756extern long ext2_ioctl(struct file *, unsigned int, unsigned long);756extern long ext2_ioctl(struct file *, unsigned int, unsigned long);
757extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);757extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);
758 758
fs/ext2/ioctl.c+2−2
@@ -18,7 +18,7 @@ · 17 unmodified lines
18#include <linux/uaccess.h>18#include <linux/uaccess.h>
19#include <linux/fileattr.h>19#include <linux/fileattr.h>
20 20
21int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa)21int ext2_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
22{22{
23 struct ext2_inode_info *ei = EXT2_I(d_inode(dentry));23 struct ext2_inode_info *ei = EXT2_I(d_inode(dentry));
24 24
@@ -28,7 +28,7 @@ int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 3 unmodified lines
28}28}
29 29
30int ext2_fileattr_set(struct mnt_idmap *idmap,30int ext2_fileattr_set(struct mnt_idmap *idmap,
31 struct dentry *dentry, struct fileattr *fa)31 struct dentry *dentry, struct file_kattr *fa)
32{32{
33 struct inode *inode = d_inode(dentry);33 struct inode *inode = d_inode(dentry);
34 struct ext2_inode_info *ei = EXT2_I(inode);34 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
3103extern long ext4_ioctl(struct file *, unsigned int, unsigned long);3103extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
3104extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);3104extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
3105int ext4_fileattr_set(struct mnt_idmap *idmap,3105int ext4_fileattr_set(struct mnt_idmap *idmap,
3106 struct dentry *dentry, struct fileattr *fa);3106 struct dentry *dentry, struct file_kattr *fa);
3107int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa);3107int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
3108extern void ext4_reset_inode_seed(struct inode *inode);3108extern void ext4_reset_inode_seed(struct inode *inode);
3109int ext4_update_overhead(struct super_block *sb, bool force);3109int ext4_update_overhead(struct super_block *sb, bool force);
3110int ext4_force_shutdown(struct super_block *sb, u32 flags);3110int 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
980 return err;980 return err;
981}981}
982 982
983int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa)983int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
984{984{
985 struct inode *inode = d_inode(dentry);985 struct inode *inode = d_inode(dentry);
986 struct ext4_inode_info *ei = EXT4_I(inode);986 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
997}997}
998 998
999int ext4_fileattr_set(struct mnt_idmap *idmap,999int ext4_fileattr_set(struct mnt_idmap *idmap,
1000 struct dentry *dentry, struct fileattr *fa)1000 struct dentry *dentry, struct file_kattr *fa)
1001{1001{
1002 struct inode *inode = d_inode(dentry);1002 struct inode *inode = d_inode(dentry);
1003 u32 flags = fa->flags;1003 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
3615int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,3615int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
3616 bool readonly, bool need_lock);3616 bool readonly, bool need_lock);
3617int f2fs_precache_extents(struct inode *inode);3617int f2fs_precache_extents(struct inode *inode);
3618int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa);3618int f2fs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
3619int f2fs_fileattr_set(struct mnt_idmap *idmap,3619int f2fs_fileattr_set(struct mnt_idmap *idmap,
3620 struct dentry *dentry, struct fileattr *fa);3620 struct dentry *dentry, struct file_kattr *fa);
3621long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);3621long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
3622long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);3622long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
3623int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid);3623int 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
3391}3391}
3392#endif3392#endif
3393 3393
3394int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa)3394int f2fs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
3395{3395{
3396 struct inode *inode = d_inode(dentry);3396 struct inode *inode = d_inode(dentry);
3397 struct f2fs_inode_info *fi = F2FS_I(inode);3397 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
3415}3415}
3416 3416
3417int f2fs_fileattr_set(struct mnt_idmap *idmap,3417int f2fs_fileattr_set(struct mnt_idmap *idmap,
3418 struct dentry *dentry, struct fileattr *fa)3418 struct dentry *dentry, struct file_kattr *fa)
3419{3419{
3420 struct inode *inode = d_inode(dentry);3420 struct inode *inode = d_inode(dentry);
3421 u32 fsflags = fa->flags, mask = F2FS_SETTABLE_FS_FL;3421 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 */
20void 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}
40EXPORT_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 */
50void 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}
70EXPORT_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 */
81int 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}
95EXPORT_SYMBOL(vfs_fileattr_get);
96
97static 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 */
117int 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}
134EXPORT_SYMBOL(copy_fsxattr_to_user);
135
136static 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
153static 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 */
181static 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 */
265int 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
303out:
304 inode_unlock(inode);
305 return err;
306}
307EXPORT_SYMBOL(vfs_fileattr_set);
308
309int 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}
321EXPORT_SYMBOL(ioctl_getflags);
322
323int 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}
344EXPORT_SYMBOL(ioctl_setflags);
345
346int 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}
359EXPORT_SYMBOL(ioctl_fsgetxattr);
360
361int 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}
380EXPORT_SYMBOL(ioctl_fssetxattr);
381
382SYSCALL_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
437SYSCALL_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
1479long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);1479long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
1480long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,1480long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
1481 unsigned long arg);1481 unsigned long arg);
1482int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa);1482int fuse_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
1483int fuse_fileattr_set(struct mnt_idmap *idmap,1483int fuse_fileattr_set(struct mnt_idmap *idmap,
1484 struct dentry *dentry, struct fileattr *fa);1484 struct dentry *dentry, struct file_kattr *fa);
1485 1485
1486/* iomode.c */1486/* iomode.c */
1487int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff);1487int 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
502 fuse_file_release(inode, ff, O_RDONLY, NULL, S_ISDIR(inode->i_mode));502 fuse_file_release(inode, ff, O_RDONLY, NULL, S_ISDIR(inode->i_mode));
503}503}
504 504
505int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa)505int fuse_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
506{506{
507 struct inode *inode = d_inode(dentry);507 struct inode *inode = d_inode(dentry);
508 struct fuse_file *ff;508 struct fuse_file *ff;
@@ -536,11 +536,13 @@ int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 27 unmodified lines
536cleanup:536cleanup:
537 fuse_priv_ioctl_cleanup(inode, ff);537 fuse_priv_ioctl_cleanup(inode, ff);
538 538
539 if (err == -ENOTTY)
540 err = -EOPNOTSUPP;
539 return err;541 return err;
540}542}
541 543
542int fuse_fileattr_set(struct mnt_idmap *idmap,544int fuse_fileattr_set(struct mnt_idmap *idmap,
543 struct dentry *dentry, struct fileattr *fa)545 struct dentry *dentry, struct file_kattr *fa)
544{546{
545 struct inode *inode = d_inode(dentry);547 struct inode *inode = d_inode(dentry);
546 struct fuse_file *ff;548 struct fuse_file *ff;
@@ -572,5 +574,7 @@ int fuse_fileattr_set(struct mnt_idmap *idmap, · 25 unmodified lines
572cleanup:574cleanup:
573 fuse_priv_ioctl_cleanup(inode, ff);575 fuse_priv_ioctl_cleanup(inode, ff);
574 576
577 if (err == -ENOTTY)
578 err = -EOPNOTSUPP;
575 return err;579 return err;
576}580}
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
155 return fsflags;155 return fsflags;
156}156}
157 157
158int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa)158int gfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
159{159{
160 struct inode *inode = d_inode(dentry);160 struct inode *inode = d_inode(dentry);
161 struct gfs2_inode *ip = GFS2_I(inode);161 struct gfs2_inode *ip = GFS2_I(inode);
@@ -276,7 +276,7 @@ out: · 114 unmodified lines
276}276}
277 277
278int gfs2_fileattr_set(struct mnt_idmap *idmap,278int gfs2_fileattr_set(struct mnt_idmap *idmap,
279 struct dentry *dentry, struct fileattr *fa)279 struct dentry *dentry, struct file_kattr *fa)
280{280{
281 struct inode *inode = d_inode(dentry);281 struct inode *inode = d_inode(dentry);
282 u32 fsflags = fa->flags, gfsflags = 0;282 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
107extern const struct file_operations gfs2_file_fops_nolock;107extern const struct file_operations gfs2_file_fops_nolock;
108extern const struct file_operations gfs2_dir_fops_nolock;108extern const struct file_operations gfs2_dir_fops_nolock;
109 109
110int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);110int gfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
111int gfs2_fileattr_set(struct mnt_idmap *idmap,111int gfs2_fileattr_set(struct mnt_idmap *idmap,
112 struct dentry *dentry, struct fileattr *fa);112 struct dentry *dentry, struct file_kattr *fa);
113void gfs2_set_inode_flags(struct inode *inode);113void gfs2_set_inode_flags(struct inode *inode);
114 114
115#ifdef CONFIG_GFS2_FS_LOCKING_DLM115#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
491 unsigned int query_flags);491 unsigned int query_flags);
492int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,492int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
493 int datasync);493 int datasync);
494int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa);494int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
495int hfsplus_fileattr_set(struct mnt_idmap *idmap,495int hfsplus_fileattr_set(struct mnt_idmap *idmap,
496 struct dentry *dentry, struct fileattr *fa);496 struct dentry *dentry, struct file_kattr *fa);
497 497
498/* ioctl.c */498/* ioctl.c */
499long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);499long 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
656 return res;656 return res;
657}657}
658 658
659int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa)659int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
660{660{
661 struct inode *inode = d_inode(dentry);661 struct inode *inode = d_inode(dentry);
662 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);662 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
675}675}
676 676
677int hfsplus_fileattr_set(struct mnt_idmap *idmap,677int hfsplus_fileattr_set(struct mnt_idmap *idmap,
678 struct dentry *dentry, struct fileattr *fa)678 struct dentry *dentry, struct file_kattr *fa)
679{679{
680 struct inode *inode = d_inode(dentry);680 struct inode *inode = d_inode(dentry);
681 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);681 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
fs/ioctl.c+0−309
@@ -453,315 +453,6 @@ out: · 452 unmodified lines
453 return ret;453 return ret;
454}454}
455 455
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 */
464void 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}
484EXPORT_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 */
494void 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}
514EXPORT_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 */
525int 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}
534EXPORT_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 */
543int 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}
559EXPORT_SYMBOL(copy_fsxattr_to_user);
560
561static 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 */
584static 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 */
668int 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}
702EXPORT_SYMBOL(vfs_fileattr_set);
703
704static 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
715static 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
735static 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
747static 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
765static int ioctl_getfsuuid(struct file *file, void __user *argp)456static int ioctl_getfsuuid(struct file *file, void __user *argp)
766{457{
767 struct super_block *sb = file_inode(file)->i_sb;458 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
57 return mapped;57 return mapped;
58}58}
59 59
60int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)60int jfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
61{61{
62 struct jfs_inode_info *jfs_inode = JFS_IP(d_inode(dentry));62 struct jfs_inode_info *jfs_inode = JFS_IP(d_inode(dentry));
63 unsigned int flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;63 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
71}71}
72 72
73int jfs_fileattr_set(struct mnt_idmap *idmap,73int jfs_fileattr_set(struct mnt_idmap *idmap,
74 struct dentry *dentry, struct fileattr *fa)74 struct dentry *dentry, struct file_kattr *fa)
75{75{
76 struct inode *inode = d_inode(dentry);76 struct inode *inode = d_inode(dentry);
77 struct jfs_inode_info *jfs_inode = JFS_IP(inode);77 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
9 9
10extern struct inode *ialloc(struct inode *, umode_t);10extern struct inode *ialloc(struct inode *, umode_t);
11extern int jfs_fsync(struct file *, loff_t, loff_t, int);11extern int jfs_fsync(struct file *, loff_t, loff_t, int);
12extern int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);12extern int jfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
13extern int jfs_fileattr_set(struct mnt_idmap *idmap,13extern int jfs_fileattr_set(struct mnt_idmap *idmap,
14 struct dentry *dentry, struct fileattr *fa);14 struct dentry *dentry, struct file_kattr *fa);
15extern long jfs_ioctl(struct file *, unsigned int, unsigned long);15extern long jfs_ioctl(struct file *, unsigned int, unsigned long);
16extern struct inode *jfs_iget(struct super_block *, unsigned long);16extern struct inode *jfs_iget(struct super_block *, unsigned long);
17extern int jfs_commit_inode(struct inode *, int);17extern 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
118 *118 *
119 * Return: always 0 as success.119 * Return: always 0 as success.
120 */120 */
121int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)121int nilfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
122{122{
123 struct inode *inode = d_inode(dentry);123 struct inode *inode = d_inode(dentry);
124 124
@@ -136,7 +136,7 @@ int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 11 unmodified lines
136 * Return: 0 on success, or a negative error code on failure.136 * Return: 0 on success, or a negative error code on failure.
137 */137 */
138int nilfs_fileattr_set(struct mnt_idmap *idmap,138int nilfs_fileattr_set(struct mnt_idmap *idmap,
139 struct dentry *dentry, struct fileattr *fa)139 struct dentry *dentry, struct file_kattr *fa)
140{140{
141 struct inode *inode = d_inode(dentry);141 struct inode *inode = d_inode(dentry);
142 struct nilfs_transaction_info ti;142 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
268extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);268extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
269 269
270/* ioctl.c */270/* ioctl.c */
271int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *m);271int nilfs_fileattr_get(struct dentry *dentry, struct file_kattr *m);
272int nilfs_fileattr_set(struct mnt_idmap *idmap,272int nilfs_fileattr_set(struct mnt_idmap *idmap,
273 struct dentry *dentry, struct fileattr *fa);273 struct dentry *dentry, struct file_kattr *fa);
274long nilfs_ioctl(struct file *, unsigned int, unsigned long);274long nilfs_ioctl(struct file *, unsigned int, unsigned long);
275long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);275long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
276int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,276int 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
62 return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));62 return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));
63}63}
64 64
65int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa)65int ocfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
66{66{
67 struct inode *inode = d_inode(dentry);67 struct inode *inode = d_inode(dentry);
68 unsigned int flags;68 unsigned int flags;
@@ -83,7 +83,7 @@ int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 14 unmodified lines
83}83}
84 84
85int ocfs2_fileattr_set(struct mnt_idmap *idmap,85int ocfs2_fileattr_set(struct mnt_idmap *idmap,
86 struct dentry *dentry, struct fileattr *fa)86 struct dentry *dentry, struct file_kattr *fa)
87{87{
88 struct inode *inode = d_inode(dentry);88 struct inode *inode = d_inode(dentry);
89 unsigned int flags = fa->flags;89 unsigned int flags = fa->flags;
fs/ocfs2/ioctl.h+2−2
@@ -11,9 +11,9 @@ · 10 unmodified lines
11#ifndef OCFS2_IOCTL_PROTO_H11#ifndef OCFS2_IOCTL_PROTO_H
12#define OCFS2_IOCTL_PROTO_H12#define OCFS2_IOCTL_PROTO_H
13 13
14int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);14int ocfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
15int ocfs2_fileattr_set(struct mnt_idmap *idmap,15int ocfs2_fileattr_set(struct mnt_idmap *idmap,
16 struct dentry *dentry, struct fileattr *fa);16 struct dentry *dentry, struct file_kattr *fa);
17long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);17long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
18long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);18long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
19 19
fs/orangefs/inode.c+2−2
@@ -889,7 +889,7 @@ int orangefs_update_time(struct inode *inode, int flags) · 888 unmodified lines
889 return __orangefs_setattr(inode, &iattr);889 return __orangefs_setattr(inode, &iattr);
890}890}
891 891
892static int orangefs_fileattr_get(struct dentry *dentry, struct fileattr *fa)892static int orangefs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
893{893{
894 u64 val = 0;894 u64 val = 0;
895 int ret;895 int ret;
@@ -910,7 +910,7 @@ static int orangefs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 14 unmodified lines
910}910}
911 911
912static int orangefs_fileattr_set(struct mnt_idmap *idmap,912static int orangefs_fileattr_set(struct mnt_idmap *idmap,
913 struct dentry *dentry, struct fileattr *fa)913 struct dentry *dentry, struct file_kattr *fa)
914{914{
915 u64 val = 0;915 u64 val = 0;
916 916
fs/overlayfs/copy_up.c+3−3
@@ -171,14 +171,14 @@ out: · 170 unmodified lines
171static int ovl_copy_fileattr(struct inode *inode, const struct path *old,171static int ovl_copy_fileattr(struct inode *inode, const struct path *old,
172 const struct path *new)172 const struct path *new)
173{173{
174 struct fileattr oldfa = { .flags_valid = true };174 struct file_kattr oldfa = { .flags_valid = true };
175 struct fileattr newfa = { .flags_valid = true };175 struct file_kattr newfa = { .flags_valid = true };
176 int err;176 int err;
177 177
178 err = ovl_real_fileattr_get(old, &oldfa);178 err = ovl_real_fileattr_get(old, &oldfa);
179 if (err) {179 if (err) {
180 /* Ntfs-3g returns -EINVAL for "no fileattr support" */180 /* Ntfs-3g returns -EINVAL for "no fileattr support" */
181 if (err == -ENOTTY || err == -EINVAL)181 if (err == -EOPNOTSUPP || err == -EINVAL)
182 return 0;182 return 0;
183 pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n",183 pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n",
184 old->dentry, err);184 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
610 * Introducing security_inode_fileattr_get/set() hooks would solve this issue610 * Introducing security_inode_fileattr_get/set() hooks would solve this issue
611 * properly.611 * properly.
612 */612 */
613static int ovl_security_fileattr(const struct path *realpath, struct fileattr *fa,613static int ovl_security_fileattr(const struct path *realpath, struct file_kattr *fa,
614 bool set)614 bool set)
615{615{
616 struct file *file;616 struct file *file;
@@ -637,7 +637,7 @@ static int ovl_security_fileattr(const struct path *realpath, struct fileattr *f · 20 unmodified lines
637 return err;637 return err;
638}638}
639 639
640int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa)640int ovl_real_fileattr_set(const struct path *realpath, struct file_kattr *fa)
641{641{
642 int err;642 int err;
643 643
@@ -649,7 +649,7 @@ int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa) · 5 unmodified lines
649}649}
650 650
651int ovl_fileattr_set(struct mnt_idmap *idmap,651int ovl_fileattr_set(struct mnt_idmap *idmap,
652 struct dentry *dentry, struct fileattr *fa)652 struct dentry *dentry, struct file_kattr *fa)
653{653{
654 struct inode *inode = d_inode(dentry);654 struct inode *inode = d_inode(dentry);
655 struct path upperpath;655 struct path upperpath;
@@ -697,7 +697,7 @@ out: · 41 unmodified lines
697}697}
698 698
699/* Convert inode protection flags to fileattr flags */699/* Convert inode protection flags to fileattr flags */
700static void ovl_fileattr_prot_flags(struct inode *inode, struct fileattr *fa)700static void ovl_fileattr_prot_flags(struct inode *inode, struct file_kattr *fa)
701{701{
702 BUILD_BUG_ON(OVL_PROT_FS_FLAGS_MASK & ~FS_COMMON_FL);702 BUILD_BUG_ON(OVL_PROT_FS_FLAGS_MASK & ~FS_COMMON_FL);
703 BUILD_BUG_ON(OVL_PROT_FSX_FLAGS_MASK & ~FS_XFLAG_COMMON);703 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
712 }712 }
713}713}
714 714
715int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa)715int ovl_real_fileattr_get(const struct path *realpath, struct file_kattr *fa)
716{716{
717 int err;717 int err;
718 718
@@ -720,13 +720,10 @@ int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa) · 1 unmodified line
720 if (err)720 if (err)
721 return err;721 return err;
722 722
723 err = vfs_fileattr_get(realpath->dentry, fa);723 return vfs_fileattr_get(realpath->dentry, fa);
724 if (err == -ENOIOCTLCMD)
725 err = -ENOTTY;
726 return err;
727}724}
728 725
729int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)726int ovl_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
730{727{
731 struct inode *inode = d_inode(dentry);728 struct inode *inode = d_inode(dentry);
732 struct path realpath;729 struct path realpath;
fs/overlayfs/overlayfs.h+5−5
@@ -838,7 +838,7 @@ void ovl_copyattr(struct inode *to); · 837 unmodified lines
838 838
839void ovl_check_protattr(struct inode *inode, struct dentry *upper);839void ovl_check_protattr(struct inode *inode, struct dentry *upper);
840int ovl_set_protattr(struct inode *inode, struct dentry *upper,840int ovl_set_protattr(struct inode *inode, struct dentry *upper,
841 struct fileattr *fa);841 struct file_kattr *fa);
842 842
843static inline void ovl_copyflags(struct inode *from, struct inode *to)843static inline void ovl_copyflags(struct inode *from, struct inode *to)
844{844{
@@ -870,11 +870,11 @@ struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir, · 25 unmodified lines
870 870
871/* file.c */871/* file.c */
872extern const struct file_operations ovl_file_operations;872extern const struct file_operations ovl_file_operations;
873int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa);873int ovl_real_fileattr_get(const struct path *realpath, struct file_kattr *fa);
874int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa);874int ovl_real_fileattr_set(const struct path *realpath, struct file_kattr *fa);
875int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa);875int ovl_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
876int ovl_fileattr_set(struct mnt_idmap *idmap,876int ovl_fileattr_set(struct mnt_idmap *idmap,
877 struct dentry *dentry, struct fileattr *fa);877 struct dentry *dentry, struct file_kattr *fa);
878struct ovl_file;878struct ovl_file;
879struct ovl_file *ovl_file_alloc(struct file *realfile);879struct ovl_file *ovl_file_alloc(struct file *realfile);
880void ovl_file_free(struct ovl_file *of);880void 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
966}966}
967 967
968int ovl_set_protattr(struct inode *inode, struct dentry *upper,968int ovl_set_protattr(struct inode *inode, struct dentry *upper,
969 struct fileattr *fa)969 struct file_kattr *fa)
970{970{
971 struct ovl_fs *ofs = OVL_FS(inode->i_sb);971 struct ovl_fs *ofs = OVL_FS(inode->i_sb);
972 char buf[OVL_PROTATTR_MAX];972 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
130 return err;130 return err;
131}131}
132 132
133int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa)133int ubifs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
134{134{
135 struct inode *inode = d_inode(dentry);135 struct inode *inode = d_inode(dentry);
136 int flags = ubifs2ioctl(ubifs_inode(inode)->flags);136 int flags = ubifs2ioctl(ubifs_inode(inode)->flags);
@@ -145,7 +145,7 @@ int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 8 unmodified lines
145}145}
146 146
147int ubifs_fileattr_set(struct mnt_idmap *idmap,147int ubifs_fileattr_set(struct mnt_idmap *idmap,
148 struct dentry *dentry, struct fileattr *fa)148 struct dentry *dentry, struct file_kattr *fa)
149{149{
150 struct inode *inode = d_inode(dentry);150 struct inode *inode = d_inode(dentry);
151 int flags = fa->flags;151 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
2073void ubifs_destroy_size_tree(struct ubifs_info *c);2073void ubifs_destroy_size_tree(struct ubifs_info *c);
2074 2074
2075/* ioctl.c */2075/* ioctl.c */
2076int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa);2076int ubifs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
2077int ubifs_fileattr_set(struct mnt_idmap *idmap,2077int ubifs_fileattr_set(struct mnt_idmap *idmap,
2078 struct dentry *dentry, struct fileattr *fa);2078 struct dentry *dentry, struct file_kattr *fa);
2079long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);2079long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
2080void ubifs_set_inode_flags(struct inode *inode);2080void ubifs_set_inode_flags(struct inode *inode);
2081#ifdef CONFIG_COMPAT2081#ifdef CONFIG_COMPAT
fs/xfs/xfs_ioctl.c+9−9
@@ -444,7 +444,7 @@ static void · 443 unmodified lines
444xfs_fill_fsxattr(444xfs_fill_fsxattr(
445 struct xfs_inode *ip,445 struct xfs_inode *ip,
446 int whichfork,446 int whichfork,
447 struct fileattr *fa)447 struct file_kattr *fa)
448{448{
449 struct xfs_mount *mp = ip->i_mount;449 struct xfs_mount *mp = ip->i_mount;
450 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);450 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
@@ -496,7 +496,7 @@ xfs_ioc_fsgetxattra( · 45 unmodified lines
496 xfs_inode_t *ip,496 xfs_inode_t *ip,
497 void __user *arg)497 void __user *arg)
498{498{
499 struct fileattr fa;499 struct file_kattr fa;
500 500
501 xfs_ilock(ip, XFS_ILOCK_SHARED);501 xfs_ilock(ip, XFS_ILOCK_SHARED);
502 xfs_fill_fsxattr(ip, XFS_ATTR_FORK, &fa);502 xfs_fill_fsxattr(ip, XFS_ATTR_FORK, &fa);
@@ -508,7 +508,7 @@ xfs_ioc_fsgetxattra( · 5 unmodified lines
508int508int
509xfs_fileattr_get(509xfs_fileattr_get(
510 struct dentry *dentry,510 struct dentry *dentry,
511 struct fileattr *fa)511 struct file_kattr *fa)
512{512{
513 struct xfs_inode *ip = XFS_I(d_inode(dentry));513 struct xfs_inode *ip = XFS_I(d_inode(dentry));
514 514
@@ -526,7 +526,7 @@ static int · 11 unmodified lines
526xfs_ioctl_setattr_xflags(526xfs_ioctl_setattr_xflags(
527 struct xfs_trans *tp,527 struct xfs_trans *tp,
528 struct xfs_inode *ip,528 struct xfs_inode *ip,
529 struct fileattr *fa)529 struct file_kattr *fa)
530{530{
531 struct xfs_mount *mp = ip->i_mount;531 struct xfs_mount *mp = ip->i_mount;
532 bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);532 bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);
@@ -582,7 +582,7 @@ xfs_ioctl_setattr_xflags( · 49 unmodified lines
582static void582static void
583xfs_ioctl_setattr_prepare_dax(583xfs_ioctl_setattr_prepare_dax(
584 struct xfs_inode *ip,584 struct xfs_inode *ip,
585 struct fileattr *fa)585 struct file_kattr *fa)
586{586{
587 struct xfs_mount *mp = ip->i_mount;587 struct xfs_mount *mp = ip->i_mount;
588 struct inode *inode = VFS_I(ip);588 struct inode *inode = VFS_I(ip);
@@ -642,7 +642,7 @@ out_error: · 53 unmodified lines
642static int642static int
643xfs_ioctl_setattr_check_extsize(643xfs_ioctl_setattr_check_extsize(
644 struct xfs_inode *ip,644 struct xfs_inode *ip,
645 struct fileattr *fa)645 struct file_kattr *fa)
646{646{
647 struct xfs_mount *mp = ip->i_mount;647 struct xfs_mount *mp = ip->i_mount;
648 xfs_failaddr_t failaddr;648 xfs_failaddr_t failaddr;
@@ -684,7 +684,7 @@ xfs_ioctl_setattr_check_extsize( · 35 unmodified lines
684static int684static int
685xfs_ioctl_setattr_check_cowextsize(685xfs_ioctl_setattr_check_cowextsize(
686 struct xfs_inode *ip,686 struct xfs_inode *ip,
687 struct fileattr *fa)687 struct file_kattr *fa)
688{688{
689 struct xfs_mount *mp = ip->i_mount;689 struct xfs_mount *mp = ip->i_mount;
690 xfs_failaddr_t failaddr;690 xfs_failaddr_t failaddr;
@@ -709,7 +709,7 @@ xfs_ioctl_setattr_check_cowextsize( · 18 unmodified lines
709static int709static int
710xfs_ioctl_setattr_check_projid(710xfs_ioctl_setattr_check_projid(
711 struct xfs_inode *ip,711 struct xfs_inode *ip,
712 struct fileattr *fa)712 struct file_kattr *fa)
713{713{
714 if (!fa->fsx_valid)714 if (!fa->fsx_valid)
715 return 0;715 return 0;
@@ -725,7 +725,7 @@ int · 9 unmodified lines
725xfs_fileattr_set(725xfs_fileattr_set(
726 struct mnt_idmap *idmap,726 struct mnt_idmap *idmap,
727 struct dentry *dentry,727 struct dentry *dentry,
728 struct fileattr *fa)728 struct file_kattr *fa)
729{729{
730 struct xfs_inode *ip = XFS_I(d_inode(dentry));730 struct xfs_inode *ip = XFS_I(d_inode(dentry));
731 struct xfs_mount *mp = ip->i_mount;731 struct xfs_mount *mp = ip->i_mount;
fs/xfs/xfs_ioctl.h+2−2
@@ -17,13 +17,13 @@ xfs_ioc_swapext( · 16 unmodified lines
17extern int17extern int
18xfs_fileattr_get(18xfs_fileattr_get(
19 struct dentry *dentry,19 struct dentry *dentry,
20 struct fileattr *fa);20 struct file_kattr *fa);
21 21
22extern int22extern int
23xfs_fileattr_set(23xfs_fileattr_set(
24 struct mnt_idmap *idmap,24 struct mnt_idmap *idmap,
25 struct dentry *dentry,25 struct dentry *dentry,
26 struct fileattr *fa);26 struct file_kattr *fa);
27 27
28extern long28extern long
29xfs_file_ioctl(29xfs_file_ioctl(
include/linux/fileattr.h+31−7
@@ -14,13 +14,33 @@ · 13 unmodified lines
14 FS_XFLAG_NODUMP | FS_XFLAG_NOATIME | FS_XFLAG_DAX | \14 FS_XFLAG_NODUMP | FS_XFLAG_NOATIME | FS_XFLAG_DAX | \
15 FS_XFLAG_PROJINHERIT)15 FS_XFLAG_PROJINHERIT)
16 16
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
17/*37/*
18 * Merged interface for miscellaneous file attributes. 'flags' originates from38 * Merged interface for miscellaneous file attributes. 'flags' originates from
19 * ext* and 'fsx_flags' from xfs. There's some overlap between the two, which39 * ext* and 'fsx_flags' from xfs. There's some overlap between the two, which
20 * is handled by the VFS helpers, so filesystems are free to implement just one40 * is handled by the VFS helpers, so filesystems are free to implement just one
21 * or both of these sub-interfaces.41 * or both of these sub-interfaces.
22 */42 */
23struct fileattr {43struct file_kattr {
24 u32 flags; /* flags (FS_IOC_GETFLAGS/FS_IOC_SETFLAGS) */44 u32 flags; /* flags (FS_IOC_GETFLAGS/FS_IOC_SETFLAGS) */
25 /* struct fsxattr: */45 /* struct fsxattr: */
26 u32 fsx_xflags; /* xflags field value (get/set) */46 u32 fsx_xflags; /* xflags field value (get/set) */
@@ -33,10 +53,10 @@ struct fileattr { · 6 unmodified lines
33 bool fsx_valid:1;53 bool fsx_valid:1;
34};54};
35 55
36int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa);56int copy_fsxattr_to_user(const struct file_kattr *fa, struct fsxattr __user *ufa);
37 57
38void fileattr_fill_xflags(struct fileattr *fa, u32 xflags);58void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags);
39void fileattr_fill_flags(struct fileattr *fa, u32 flags);59void fileattr_fill_flags(struct file_kattr *fa, u32 flags);
40 60
41/**61/**
42 * fileattr_has_fsx - check for extended flags/attributes62 * fileattr_has_fsx - check for extended flags/attributes
@@ -45,15 +65,19 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flags); · 2 unmodified lines
45 * Return: true if any attributes are present that are not represented in65 * Return: true if any attributes are present that are not represented in
46 * ->flags.66 * ->flags.
47 */67 */
48static inline bool fileattr_has_fsx(const struct fileattr *fa)68static inline bool fileattr_has_fsx(const struct file_kattr *fa)
49{69{
50 return fa->fsx_valid &&70 return fa->fsx_valid &&
51 ((fa->fsx_xflags & ~FS_XFLAG_COMMON) || fa->fsx_extsize != 0 ||71 ((fa->fsx_xflags & ~FS_XFLAG_COMMON) || fa->fsx_extsize != 0 ||
52 fa->fsx_projid != 0 || fa->fsx_cowextsize != 0);72 fa->fsx_projid != 0 || fa->fsx_cowextsize != 0);
53}73}
54 74
55int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);75int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
56int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,76int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
57 struct fileattr *fa);77 struct file_kattr *fa);
78int ioctl_getflags(struct file *file, unsigned int __user *argp);
79int ioctl_setflags(struct file *file, unsigned int __user *argp);
80int ioctl_fsgetxattr(struct file *file, void __user *argp);
81int ioctl_fssetxattr(struct file *file, void __user *argp);
58 82
59#endif /* _LINUX_FILEATTR_H */83#endif /* _LINUX_FILEATTR_H */
include/linux/fs.h+3−3
@@ -80,7 +80,7 @@ struct fsnotify_mark_connector; · 79 unmodified lines
80struct fsnotify_sb_info;80struct fsnotify_sb_info;
81struct fs_context;81struct fs_context;
82struct fs_parameter_spec;82struct fs_parameter_spec;
83struct fileattr;83struct file_kattr;
84struct iomap_ops;84struct iomap_ops;
85 85
86extern void __init inode_init(void);86extern void __init inode_init(void);
@@ -2257,8 +2257,8 @@ struct inode_operations { · 2170 unmodified lines
2257 int (*set_acl)(struct mnt_idmap *, struct dentry *,2257 int (*set_acl)(struct mnt_idmap *, struct dentry *,
2258 struct posix_acl *, int);2258 struct posix_acl *, int);
2259 int (*fileattr_set)(struct mnt_idmap *idmap,2259 int (*fileattr_set)(struct mnt_idmap *idmap,
2260 struct dentry *dentry, struct fileattr *fa);2260 struct dentry *dentry, struct file_kattr *fa);
2261 int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);2261 int (*fileattr_get)(struct dentry *dentry, struct file_kattr *fa);
2262 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);2262 struct offset_ctx *(*get_offset_ctx)(struct inode *inode);
2263} ____cacheline_aligned;2263} ____cacheline_aligned;
2264 2264
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
157 struct dentry *dentry, const char *name)157 struct dentry *dentry, const char *name)
158LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry,158LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry,
159 const char *name)159 const char *name)
160LSM_HOOK(int, 0, inode_file_setattr, struct dentry *dentry, struct file_kattr *fa)
161LSM_HOOK(int, 0, inode_file_getattr, struct dentry *dentry, struct file_kattr *fa)
160LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap,162LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap,
161 struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)163 struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)
162LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry,164LSM_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
451int security_inode_removexattr(struct mnt_idmap *idmap,451int security_inode_removexattr(struct mnt_idmap *idmap,
452 struct dentry *dentry, const char *name);452 struct dentry *dentry, const char *name);
453void security_inode_post_removexattr(struct dentry *dentry, const char *name);453void security_inode_post_removexattr(struct dentry *dentry, const char *name);
454int security_inode_file_setattr(struct dentry *dentry,
455 struct file_kattr *fa);
456int security_inode_file_getattr(struct dentry *dentry,
457 struct file_kattr *fa);
454int security_inode_need_killpriv(struct dentry *dentry);458int security_inode_need_killpriv(struct dentry *dentry);
455int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry);459int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry);
456int security_inode_getsecurity(struct mnt_idmap *idmap,460int security_inode_getsecurity(struct mnt_idmap *idmap,
@@ -1052,6 +1056,18 @@ static inline void security_inode_post_removexattr(struct dentry *dentry, · 595 unmodified lines
1052 const char *name)1056 const char *name)
1053{ }1057{ }
1054 1058
1059static inline int security_inode_file_setattr(struct dentry *dentry,
1060 struct file_kattr *fa)
1061{
1062 return 0;
1063}
1064
1065static inline int security_inode_file_getattr(struct dentry *dentry,
1066 struct file_kattr *fa)
1067{
1068 return 0;
1069}
1070
1055static inline int security_inode_need_killpriv(struct dentry *dentry)1071static inline int security_inode_need_killpriv(struct dentry *dentry)
1056{1072{
1057 return cap_inode_need_killpriv(dentry);1073 return cap_inode_need_killpriv(dentry);
include/linux/syscalls.h+7−0
@@ -78,6 +78,7 @@ struct cachestat; · 77 unmodified lines
78struct statmount;78struct statmount;
79struct mnt_id_req;79struct mnt_id_req;
80struct xattr_args;80struct xattr_args;
81struct file_attr;
81 82
82#include <linux/types.h>83#include <linux/types.h>
83#include <linux/aio_abi.h>84#include <linux/aio_abi.h>
@@ -371,6 +372,12 @@ asmlinkage long sys_removexattrat(int dfd, const char __user *path, · 287 unmodified lines
371asmlinkage long sys_lremovexattr(const char __user *path,372asmlinkage long sys_lremovexattr(const char __user *path,
372 const char __user *name);373 const char __user *name);
373asmlinkage long sys_fremovexattr(int fd, const char __user *name);374asmlinkage long sys_fremovexattr(int fd, const char __user *name);
375asmlinkage long sys_file_getattr(int dfd, const char __user *filename,
376 struct file_attr __user *attr, size_t usize,
377 unsigned int at_flags);
378asmlinkage long sys_file_setattr(int dfd, const char __user *filename,
379 struct file_attr __user *attr, size_t usize,
380 unsigned int at_flags);
374asmlinkage long sys_getcwd(char __user *buf, unsigned long size);381asmlinkage long sys_getcwd(char __user *buf, unsigned long size);
375asmlinkage long sys_eventfd2(unsigned int count, int flags);382asmlinkage long sys_eventfd2(unsigned int count, int flags);
376asmlinkage long sys_epoll_create1(int flags);383asmlinkage 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
852#define __NR_open_tree_attr 467852#define __NR_open_tree_attr 467
853__SYSCALL(__NR_open_tree_attr, sys_open_tree_attr)853__SYSCALL(__NR_open_tree_attr, sys_open_tree_attr)
854 854
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
855#undef __NR_syscalls861#undef __NR_syscalls
856#define __NR_syscalls 468862#define __NR_syscalls 470
857 863
858/*864/*
859 * 32 bit systems traditionally used different865 * 32 bit systems traditionally used different
include/uapi/linux/fs.h+18−0
@@ -216,6 +216,24 @@ struct fsxattr { · 215 unmodified lines
216 unsigned char fsx_pad[8];216 unsigned char fsx_pad[8];
217};217};
218 218
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 */
226struct 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
219/*237/*
220 * Flags for the fsx_xflags field238 * Flags for the fsx_xflags field
221 */239 */
mm/shmem.c+2−2
@@ -4187,7 +4187,7 @@ static const char *shmem_get_link(struct dentry *dentry, struct inode *inode, · 4186 unmodified lines
4187 4187
4188#ifdef CONFIG_TMPFS_XATTR4188#ifdef CONFIG_TMPFS_XATTR
4189 4189
4190static int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)4190static int shmem_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
4191{4191{
4192 struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));4192 struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
4193 4193
@@ -4197,7 +4197,7 @@ static int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa) · 3 unmodified lines
4197}4197}
4198 4198
4199static int shmem_fileattr_set(struct mnt_idmap *idmap,4199static int shmem_fileattr_set(struct mnt_idmap *idmap,
4200 struct dentry *dentry, struct fileattr *fa)4200 struct dentry *dentry, struct file_kattr *fa)
4201{4201{
4202 struct inode *inode = d_inode(dentry);4202 struct inode *inode = d_inode(dentry);
4203 struct shmem_inode_info *info = SHMEM_I(inode);4203 struct shmem_inode_info *info = SHMEM_I(inode);
scripts/syscall.tbl+2−0
@@ -408,3 +408,5 @@ · 407 unmodified lines
408465 common listxattrat sys_listxattrat408465 common listxattrat sys_listxattrat
409466 common removexattrat sys_removexattrat409466 common removexattrat sys_removexattrat
410467 common open_tree_attr sys_open_tree_attr410467 common open_tree_attr sys_open_tree_attr
411468 common file_getattr sys_file_getattr
412469 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
2622 call_void_hook(inode_post_removexattr, dentry, name);2622 call_void_hook(inode_post_removexattr, dentry, name);
2623}2623}
2624 2624
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 */
2635int 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 */
2650int security_inode_file_getattr(struct dentry *dentry, struct file_kattr *fa)
2651{
2652 return call_int_hook(inode_file_getattr, dentry, fa);
2653}
2654
2625/**2655/**
2626 * security_inode_need_killpriv() - Check if security_inode_killpriv() required2656 * security_inode_need_killpriv() - Check if security_inode_killpriv() required
2627 * @dentry: associated dentry2657 * @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
3480 return -EACCES;3480 return -EACCES;
3481}3481}
3482 3482
3483static 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
3489static 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
3483static int selinux_path_notify(const struct path *path, u64 mask,3495static int selinux_path_notify(const struct path *path, u64 mask,
3484 unsigned int obj_type)3496 unsigned int obj_type)
3485{3497{
@@ -7350,6 +7362,8 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { · 3864 unmodified lines
7350 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),7362 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
7351 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),7363 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
7352 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),7364 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),
7353 LSM_HOOK_INIT(inode_set_acl, selinux_inode_set_acl),7367 LSM_HOOK_INIT(inode_set_acl, selinux_inode_set_acl),
7354 LSM_HOOK_INIT(inode_get_acl, selinux_inode_get_acl),7368 LSM_HOOK_INIT(inode_get_acl, selinux_inode_get_acl),
7355 LSM_HOOK_INIT(inode_remove_acl, selinux_inode_remove_acl),7369 LSM_HOOK_INIT(inode_remove_acl, selinux_inode_remove_acl),