Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'fs.acl.rework.prep.v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping

Pull vfs acl updates from Christian Brauner:
"These are general fixes and preparatory changes related to the ongoing
posix acl rework. The actual rework where we build a type safe posix
acl api wasn't ready for this merge window but we're hopeful for the
next merge window.

General fixes:

- Some filesystems like 9p and cifs have to implement custom posix
acl handlers because they require access to the dentry in order to
set and get posix acls while the set and get inode operations
currently don't. But the ntfs3 filesystem has no such requirement
and thus implemented custom posix acl xattr handlers when it really
didn't have to. So this pr contains patch that just implements set
and get inode operations for ntfs3 and switches it to rely on the
generic posix acl xattr handlers. (We would've appreciated reviews
from the ntfs3 maintainers but we didn't get any. But hey, if we
really broke it we'll fix it. But fstests for ntfs3 said it's
fine.)

- The posix_acl_fix_xattr_common() helper has been adapted so it can
be used by a few more callers and avoiding open-coding the same
checks over and over.

Other than the two general fixes this series introduces a new helper
vfs_set_acl_prepare(). The reason for this helper is so that we can
mitigate one of the source that change {g,u}id values directly in the
uapi struct. With the vfs_set_acl_prepare() helper we can move the
idmapped mount fixup into the generic posix acl set handler.

The advantage of this is that it allows us to remove the
posix_acl_setxattr_idmapped_mnt() helper which so far we had to call
in vfs_setxattr() to account for idmapped mounts. While semantically
correct the problem with this approach was that we had to keep the
value parameter of the generic vfs_setxattr() call as non-const. This
is rectified in this series.

Ultimately, we will get rid of all the extreme kludges and type
unsafety once we have merged the posix api - hopefully during the next
merge window - built solely around get and set inode operations. Which
incidentally will also improve handling of posix acls in security and
especially in integrity modesl. While this will come with temporarily
having two inode operation for posix acls that is nothing compared to
the problems we have right now and so well worth it. We'll end up with
something that we can actually reason about instead of needing to
write novels to explain what's going on"

* tag 'fs.acl.rework.prep.v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping:
xattr: always us is_posix_acl_xattr() helper
acl: fix the comments of posix_acl_xattr_set
xattr: constify value argument in vfs_setxattr()
ovl: use vfs_set_acl_prepare()
acl: move idmapping handling into posix_acl_xattr_set()
acl: add vfs_set_acl_prepare()
acl: return EOPNOTSUPP in posix_acl_fix_xattr_common()
ntfs3: rework xattr handlers and switch to POSIX ACL VFS helpers

+264 -191
-2
fs/ntfs3/inode.c
··· 1927 1927 .setattr = ntfs3_setattr, 1928 1928 .listxattr = ntfs_listxattr, 1929 1929 .permission = ntfs_permission, 1930 - .get_acl = ntfs_get_acl, 1931 - .set_acl = ntfs_set_acl, 1932 1930 }; 1933 1931 1934 1932 const struct address_space_operations ntfs_aops = {
+6 -96
fs/ntfs3/xattr.c
··· 625 625 return ntfs_set_acl_ex(mnt_userns, inode, acl, type, false); 626 626 } 627 627 628 - static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, 629 - struct inode *inode, int type, void *buffer, 630 - size_t size) 631 - { 632 - struct posix_acl *acl; 633 - int err; 634 - 635 - if (!(inode->i_sb->s_flags & SB_POSIXACL)) { 636 - ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); 637 - return -EOPNOTSUPP; 638 - } 639 - 640 - acl = ntfs_get_acl(inode, type, false); 641 - if (IS_ERR(acl)) 642 - return PTR_ERR(acl); 643 - 644 - if (!acl) 645 - return -ENODATA; 646 - 647 - err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); 648 - posix_acl_release(acl); 649 - 650 - return err; 651 - } 652 - 653 - static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns, 654 - struct inode *inode, int type, const void *value, 655 - size_t size) 656 - { 657 - struct posix_acl *acl; 658 - int err; 659 - 660 - if (!(inode->i_sb->s_flags & SB_POSIXACL)) { 661 - ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); 662 - return -EOPNOTSUPP; 663 - } 664 - 665 - if (!inode_owner_or_capable(mnt_userns, inode)) 666 - return -EPERM; 667 - 668 - if (!value) { 669 - acl = NULL; 670 - } else { 671 - acl = posix_acl_from_xattr(&init_user_ns, value, size); 672 - if (IS_ERR(acl)) 673 - return PTR_ERR(acl); 674 - 675 - if (acl) { 676 - err = posix_acl_valid(&init_user_ns, acl); 677 - if (err) 678 - goto release_and_out; 679 - } 680 - } 681 - 682 - err = ntfs_set_acl(mnt_userns, inode, acl, type); 683 - 684 - release_and_out: 685 - posix_acl_release(acl); 686 - return err; 687 - } 688 - 689 628 /* 690 629 * ntfs_init_acl - Initialize the ACLs of a new inode. 691 630 * ··· 791 852 goto out; 792 853 } 793 854 794 - #ifdef CONFIG_NTFS3_FS_POSIX_ACL 795 - if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && 796 - !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, 797 - sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || 798 - (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && 799 - !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, 800 - sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { 801 - /* TODO: init_user_ns? */ 802 - err = ntfs_xattr_get_acl( 803 - &init_user_ns, inode, 804 - name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 805 - ? ACL_TYPE_ACCESS 806 - : ACL_TYPE_DEFAULT, 807 - buffer, size); 808 - goto out; 809 - } 810 - #endif 811 855 /* Deal with NTFS extended attribute. */ 812 856 err = ntfs_get_ea(inode, name, name_len, buffer, size, NULL); 813 857 ··· 903 981 goto out; 904 982 } 905 983 906 - #ifdef CONFIG_NTFS3_FS_POSIX_ACL 907 - if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && 908 - !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, 909 - sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || 910 - (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && 911 - !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, 912 - sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { 913 - err = ntfs_xattr_set_acl( 914 - mnt_userns, inode, 915 - name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 916 - ? ACL_TYPE_ACCESS 917 - : ACL_TYPE_DEFAULT, 918 - value, size); 919 - goto out; 920 - } 921 - #endif 922 984 /* Deal with NTFS extended attribute. */ 923 985 err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0); 924 986 ··· 992 1086 } 993 1087 994 1088 // clang-format off 995 - static const struct xattr_handler ntfs_xattr_handler = { 1089 + static const struct xattr_handler ntfs_other_xattr_handler = { 996 1090 .prefix = "", 997 1091 .get = ntfs_getxattr, 998 1092 .set = ntfs_setxattr, ··· 1000 1094 }; 1001 1095 1002 1096 const struct xattr_handler *ntfs_xattr_handlers[] = { 1003 - &ntfs_xattr_handler, 1097 + #ifdef CONFIG_NTFS3_FS_POSIX_ACL 1098 + &posix_acl_access_xattr_handler, 1099 + &posix_acl_default_xattr_handler, 1100 + #endif 1101 + &ntfs_other_xattr_handler, 1004 1102 NULL, 1005 1103 }; 1006 1104 // clang-format on
+1 -1
fs/overlayfs/overlayfs.h
··· 250 250 size_t size, int flags) 251 251 { 252 252 int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name, 253 - (void *)value, size, flags); 253 + value, size, flags); 254 254 255 255 pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n", 256 256 dentry, name, min((int)size, 48), value, size, flags, err);
+14 -1
fs/overlayfs/super.c
··· 1022 1022 1023 1023 /* Check that everything is OK before copy-up */ 1024 1024 if (value) { 1025 - acl = posix_acl_from_xattr(&init_user_ns, value, size); 1025 + /* The above comment can be understood in two ways: 1026 + * 1027 + * 1. We just want to check whether the basic POSIX ACL format 1028 + * is ok. For example, if the header is correct and the size 1029 + * is sane. 1030 + * 2. We want to know whether the ACL_{GROUP,USER} entries can 1031 + * be mapped according to the underlying filesystem. 1032 + * 1033 + * Currently, we only check 1. If we wanted to check 2. we 1034 + * would need to pass the mnt_userns and the fs_userns of the 1035 + * underlying filesystem. But frankly, I think checking 1. is 1036 + * enough to start the copy-up. 1037 + */ 1038 + acl = vfs_set_acl_prepare(&init_user_ns, &init_user_ns, value, size); 1026 1039 if (IS_ERR(acl)) 1027 1040 return PTR_ERR(acl); 1028 1041 }
+221 -67
fs/posix_acl.c
··· 710 710 /* 711 711 * Fix up the uids and gids in posix acl extended attributes in place. 712 712 */ 713 - static int posix_acl_fix_xattr_common(void *value, size_t size) 713 + static int posix_acl_fix_xattr_common(const void *value, size_t size) 714 714 { 715 - struct posix_acl_xattr_header *header = value; 715 + const struct posix_acl_xattr_header *header = value; 716 716 int count; 717 717 718 718 if (!header) ··· 720 720 if (size < sizeof(struct posix_acl_xattr_header)) 721 721 return -EINVAL; 722 722 if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 723 - return -EINVAL; 723 + return -EOPNOTSUPP; 724 724 725 725 count = posix_acl_xattr_count(size); 726 726 if (count < 0) 727 727 return -EINVAL; 728 728 if (count == 0) 729 - return -EINVAL; 729 + return 0; 730 730 731 731 return count; 732 732 } ··· 748 748 return; 749 749 750 750 count = posix_acl_fix_xattr_common(value, size); 751 - if (count < 0) 751 + if (count <= 0) 752 752 return; 753 753 754 754 for (end = entry + count; entry != end; entry++) { ··· 771 771 } 772 772 } 773 773 774 - void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns, 775 - const struct inode *inode, 776 - void *value, size_t size) 777 - { 778 - struct posix_acl_xattr_header *header = value; 779 - struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end; 780 - struct user_namespace *fs_userns = i_user_ns(inode); 781 - int count; 782 - vfsuid_t vfsuid; 783 - vfsgid_t vfsgid; 784 - kuid_t uid; 785 - kgid_t gid; 786 - 787 - if (no_idmapping(mnt_userns, i_user_ns(inode))) 788 - return; 789 - 790 - count = posix_acl_fix_xattr_common(value, size); 791 - if (count < 0) 792 - return; 793 - 794 - for (end = entry + count; entry != end; entry++) { 795 - switch (le16_to_cpu(entry->e_tag)) { 796 - case ACL_USER: 797 - uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id)); 798 - vfsuid = VFSUIDT_INIT(uid); 799 - uid = from_vfsuid(mnt_userns, fs_userns, vfsuid); 800 - entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, uid)); 801 - break; 802 - case ACL_GROUP: 803 - gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id)); 804 - vfsgid = VFSGIDT_INIT(gid); 805 - gid = from_vfsgid(mnt_userns, fs_userns, vfsgid); 806 - entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, gid)); 807 - break; 808 - default: 809 - break; 810 - } 811 - } 812 - } 813 - 814 774 static void posix_acl_fix_xattr_userns( 815 775 struct user_namespace *to, struct user_namespace *from, 816 776 void *value, size_t size) ··· 782 822 kgid_t gid; 783 823 784 824 count = posix_acl_fix_xattr_common(value, size); 785 - if (count < 0) 825 + if (count <= 0) 786 826 return; 787 827 788 828 for (end = entry + count; entry != end; entry++) { ··· 817 857 posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size); 818 858 } 819 859 820 - /* 821 - * Convert from extended attribute to in-memory representation. 860 + /** 861 + * make_posix_acl - convert POSIX ACLs from uapi to VFS format using the 862 + * provided callbacks to map ACL_{GROUP,USER} entries into the 863 + * appropriate format 864 + * @mnt_userns: the mount's idmapping 865 + * @fs_userns: the filesystem's idmapping 866 + * @value: the uapi representation of POSIX ACLs 867 + * @size: the size of @void 868 + * @uid_cb: callback to use for mapping the uid stored in ACL_USER entries 869 + * @gid_cb: callback to use for mapping the gid stored in ACL_GROUP entries 870 + * 871 + * The make_posix_acl() helper is an abstraction to translate from uapi format 872 + * into the VFS format allowing the caller to specific callbacks to map 873 + * ACL_{GROUP,USER} entries into the expected format. This is used in 874 + * posix_acl_from_xattr() and vfs_set_acl_prepare() and avoids pointless code 875 + * duplication. 876 + * 877 + * Return: Allocated struct posix_acl on success, NULL for a valid header but 878 + * without actual POSIX ACL entries, or ERR_PTR() encoded error code. 822 879 */ 823 - struct posix_acl * 824 - posix_acl_from_xattr(struct user_namespace *user_ns, 825 - const void *value, size_t size) 880 + static struct posix_acl *make_posix_acl(struct user_namespace *mnt_userns, 881 + struct user_namespace *fs_userns, const void *value, size_t size, 882 + kuid_t (*uid_cb)(struct user_namespace *, struct user_namespace *, 883 + const struct posix_acl_xattr_entry *), 884 + kgid_t (*gid_cb)(struct user_namespace *, struct user_namespace *, 885 + const struct posix_acl_xattr_entry *)) 826 886 { 827 887 const struct posix_acl_xattr_header *header = value; 828 888 const struct posix_acl_xattr_entry *entry = (const void *)(header + 1), *end; ··· 850 870 struct posix_acl *acl; 851 871 struct posix_acl_entry *acl_e; 852 872 853 - if (!value) 854 - return NULL; 855 - if (size < sizeof(struct posix_acl_xattr_header)) 856 - return ERR_PTR(-EINVAL); 857 - if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 858 - return ERR_PTR(-EOPNOTSUPP); 859 - 860 - count = posix_acl_xattr_count(size); 873 + count = posix_acl_fix_xattr_common(value, size); 861 874 if (count < 0) 862 - return ERR_PTR(-EINVAL); 875 + return ERR_PTR(count); 863 876 if (count == 0) 864 877 return NULL; 865 878 ··· 873 900 break; 874 901 875 902 case ACL_USER: 876 - acl_e->e_uid = 877 - make_kuid(user_ns, 878 - le32_to_cpu(entry->e_id)); 903 + acl_e->e_uid = uid_cb(mnt_userns, fs_userns, entry); 879 904 if (!uid_valid(acl_e->e_uid)) 880 905 goto fail; 881 906 break; 882 907 case ACL_GROUP: 883 - acl_e->e_gid = 884 - make_kgid(user_ns, 885 - le32_to_cpu(entry->e_id)); 908 + acl_e->e_gid = gid_cb(mnt_userns, fs_userns, entry); 886 909 if (!gid_valid(acl_e->e_gid)) 887 910 goto fail; 888 911 break; ··· 892 923 fail: 893 924 posix_acl_release(acl); 894 925 return ERR_PTR(-EINVAL); 926 + } 927 + 928 + /** 929 + * vfs_set_acl_prepare_kuid - map ACL_USER uid according to mount- and 930 + * filesystem idmapping 931 + * @mnt_userns: the mount's idmapping 932 + * @fs_userns: the filesystem's idmapping 933 + * @e: a ACL_USER entry in POSIX ACL uapi format 934 + * 935 + * The uid stored as ACL_USER entry in @e is a kuid_t stored as a raw {g,u}id 936 + * value. The vfs_set_acl_prepare_kuid() will recover the kuid_t through 937 + * KUIDT_INIT() and then map it according to the idmapped mount. The resulting 938 + * kuid_t is the value which the filesystem can map up into a raw backing store 939 + * id in the filesystem's idmapping. 940 + * 941 + * This is used in vfs_set_acl_prepare() to generate the proper VFS 942 + * representation of POSIX ACLs with ACL_USER entries during setxattr(). 943 + * 944 + * Return: A kuid in @fs_userns for the uid stored in @e. 945 + */ 946 + static inline kuid_t 947 + vfs_set_acl_prepare_kuid(struct user_namespace *mnt_userns, 948 + struct user_namespace *fs_userns, 949 + const struct posix_acl_xattr_entry *e) 950 + { 951 + kuid_t kuid = KUIDT_INIT(le32_to_cpu(e->e_id)); 952 + return from_vfsuid(mnt_userns, fs_userns, VFSUIDT_INIT(kuid)); 953 + } 954 + 955 + /** 956 + * vfs_set_acl_prepare_kgid - map ACL_GROUP gid according to mount- and 957 + * filesystem idmapping 958 + * @mnt_userns: the mount's idmapping 959 + * @fs_userns: the filesystem's idmapping 960 + * @e: a ACL_GROUP entry in POSIX ACL uapi format 961 + * 962 + * The gid stored as ACL_GROUP entry in @e is a kgid_t stored as a raw {g,u}id 963 + * value. The vfs_set_acl_prepare_kgid() will recover the kgid_t through 964 + * KGIDT_INIT() and then map it according to the idmapped mount. The resulting 965 + * kgid_t is the value which the filesystem can map up into a raw backing store 966 + * id in the filesystem's idmapping. 967 + * 968 + * This is used in vfs_set_acl_prepare() to generate the proper VFS 969 + * representation of POSIX ACLs with ACL_GROUP entries during setxattr(). 970 + * 971 + * Return: A kgid in @fs_userns for the gid stored in @e. 972 + */ 973 + static inline kgid_t 974 + vfs_set_acl_prepare_kgid(struct user_namespace *mnt_userns, 975 + struct user_namespace *fs_userns, 976 + const struct posix_acl_xattr_entry *e) 977 + { 978 + kgid_t kgid = KGIDT_INIT(le32_to_cpu(e->e_id)); 979 + return from_vfsgid(mnt_userns, fs_userns, VFSGIDT_INIT(kgid)); 980 + } 981 + 982 + /** 983 + * vfs_set_acl_prepare - convert POSIX ACLs from uapi to VFS format taking 984 + * mount and filesystem idmappings into account 985 + * @mnt_userns: the mount's idmapping 986 + * @fs_userns: the filesystem's idmapping 987 + * @value: the uapi representation of POSIX ACLs 988 + * @size: the size of @void 989 + * 990 + * When setting POSIX ACLs with ACL_{GROUP,USER} entries they need to be 991 + * mapped according to the relevant mount- and filesystem idmapping. It is 992 + * important that the ACL_{GROUP,USER} entries in struct posix_acl will be 993 + * mapped into k{g,u}id_t that are supposed to be mapped up in the filesystem 994 + * idmapping. This is crucial since the resulting struct posix_acl might be 995 + * cached filesystem wide. The vfs_set_acl_prepare() function will take care to 996 + * perform all necessary idmappings. 997 + * 998 + * Note, that since basically forever the {g,u}id values encoded as 999 + * ACL_{GROUP,USER} entries in the uapi POSIX ACLs passed via @value contain 1000 + * values that have been mapped according to the caller's idmapping. In other 1001 + * words, POSIX ACLs passed in uapi format as @value during setxattr() contain 1002 + * {g,u}id values in their ACL_{GROUP,USER} entries that should actually have 1003 + * been stored as k{g,u}id_t. 1004 + * 1005 + * This means, vfs_set_acl_prepare() needs to first recover the k{g,u}id_t by 1006 + * calling K{G,U}IDT_INIT(). Afterwards they can be interpreted as vfs{g,u}id_t 1007 + * through from_vfs{g,u}id() to account for any idmapped mounts. The 1008 + * vfs_set_acl_prepare_k{g,u}id() helpers will take care to generate the 1009 + * correct k{g,u}id_t. 1010 + * 1011 + * The filesystem will then receive the POSIX ACLs ready to be cached 1012 + * filesystem wide and ready to be written to the backing store taking the 1013 + * filesystem's idmapping into account. 1014 + * 1015 + * Return: Allocated struct posix_acl on success, NULL for a valid header but 1016 + * without actual POSIX ACL entries, or ERR_PTR() encoded error code. 1017 + */ 1018 + struct posix_acl *vfs_set_acl_prepare(struct user_namespace *mnt_userns, 1019 + struct user_namespace *fs_userns, 1020 + const void *value, size_t size) 1021 + { 1022 + return make_posix_acl(mnt_userns, fs_userns, value, size, 1023 + vfs_set_acl_prepare_kuid, 1024 + vfs_set_acl_prepare_kgid); 1025 + } 1026 + EXPORT_SYMBOL(vfs_set_acl_prepare); 1027 + 1028 + /** 1029 + * posix_acl_from_xattr_kuid - map ACL_USER uid into filesystem idmapping 1030 + * @mnt_userns: unused 1031 + * @fs_userns: the filesystem's idmapping 1032 + * @e: a ACL_USER entry in POSIX ACL uapi format 1033 + * 1034 + * Map the uid stored as ACL_USER entry in @e into the filesystem's idmapping. 1035 + * This is used in posix_acl_from_xattr() to generate the proper VFS 1036 + * representation of POSIX ACLs with ACL_USER entries. 1037 + * 1038 + * Return: A kuid in @fs_userns for the uid stored in @e. 1039 + */ 1040 + static inline kuid_t 1041 + posix_acl_from_xattr_kuid(struct user_namespace *mnt_userns, 1042 + struct user_namespace *fs_userns, 1043 + const struct posix_acl_xattr_entry *e) 1044 + { 1045 + return make_kuid(fs_userns, le32_to_cpu(e->e_id)); 1046 + } 1047 + 1048 + /** 1049 + * posix_acl_from_xattr_kgid - map ACL_GROUP gid into filesystem idmapping 1050 + * @mnt_userns: unused 1051 + * @fs_userns: the filesystem's idmapping 1052 + * @e: a ACL_GROUP entry in POSIX ACL uapi format 1053 + * 1054 + * Map the gid stored as ACL_GROUP entry in @e into the filesystem's idmapping. 1055 + * This is used in posix_acl_from_xattr() to generate the proper VFS 1056 + * representation of POSIX ACLs with ACL_GROUP entries. 1057 + * 1058 + * Return: A kgid in @fs_userns for the gid stored in @e. 1059 + */ 1060 + static inline kgid_t 1061 + posix_acl_from_xattr_kgid(struct user_namespace *mnt_userns, 1062 + struct user_namespace *fs_userns, 1063 + const struct posix_acl_xattr_entry *e) 1064 + { 1065 + return make_kgid(fs_userns, le32_to_cpu(e->e_id)); 1066 + } 1067 + 1068 + /** 1069 + * posix_acl_from_xattr - convert POSIX ACLs from backing store to VFS format 1070 + * @fs_userns: the filesystem's idmapping 1071 + * @value: the uapi representation of POSIX ACLs 1072 + * @size: the size of @void 1073 + * 1074 + * Filesystems that store POSIX ACLs in the unaltered uapi format should use 1075 + * posix_acl_from_xattr() when reading them from the backing store and 1076 + * converting them into the struct posix_acl VFS format. The helper is 1077 + * specifically intended to be called from the ->get_acl() inode operation. 1078 + * 1079 + * The posix_acl_from_xattr() function will map the raw {g,u}id values stored 1080 + * in ACL_{GROUP,USER} entries into the filesystem idmapping in @fs_userns. The 1081 + * posix_acl_from_xattr_k{g,u}id() helpers will take care to generate the 1082 + * correct k{g,u}id_t. The returned struct posix_acl can be cached. 1083 + * 1084 + * Note that posix_acl_from_xattr() does not take idmapped mounts into account. 1085 + * If it did it calling is from the ->get_acl() inode operation would return 1086 + * POSIX ACLs mapped according to an idmapped mount which would mean that the 1087 + * value couldn't be cached for the filesystem. Idmapped mounts are taken into 1088 + * account on the fly during permission checking or right at the VFS - 1089 + * userspace boundary before reporting them to the user. 1090 + * 1091 + * Return: Allocated struct posix_acl on success, NULL for a valid header but 1092 + * without actual POSIX ACL entries, or ERR_PTR() encoded error code. 1093 + */ 1094 + struct posix_acl * 1095 + posix_acl_from_xattr(struct user_namespace *fs_userns, 1096 + const void *value, size_t size) 1097 + { 1098 + return make_posix_acl(&init_user_ns, fs_userns, value, size, 1099 + posix_acl_from_xattr_kuid, 1100 + posix_acl_from_xattr_kgid); 895 1101 } 896 1102 EXPORT_SYMBOL (posix_acl_from_xattr); 897 1103 ··· 1171 1027 int ret; 1172 1028 1173 1029 if (value) { 1174 - acl = posix_acl_from_xattr(&init_user_ns, value, size); 1030 + /* 1031 + * By the time we end up here the {g,u}ids stored in 1032 + * ACL_{GROUP,USER} have already been mapped according to the 1033 + * caller's idmapping. The vfs_set_acl_prepare() helper will 1034 + * recover them and take idmapped mounts into account. The 1035 + * filesystem will receive the POSIX ACLs in the correct 1036 + * format ready to be cached or written to the backing store 1037 + * taking the filesystem idmapping into account. 1038 + */ 1039 + acl = vfs_set_acl_prepare(mnt_userns, i_user_ns(inode), 1040 + value, size); 1175 1041 if (IS_ERR(acl)) 1176 1042 return PTR_ERR(acl); 1177 1043 }
+4 -11
fs/xattr.c
··· 290 290 291 291 int 292 292 vfs_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry, 293 - const char *name, void *value, size_t size, int flags) 293 + const char *name, const void *value, size_t size, int flags) 294 294 { 295 295 struct inode *inode = dentry->d_inode; 296 296 struct inode *delegated_inode = NULL; ··· 298 298 int error; 299 299 300 300 if (size && strcmp(name, XATTR_NAME_CAPS) == 0) { 301 - error = cap_convert_nscap(mnt_userns, dentry, 302 - (const void **)&value, size); 301 + error = cap_convert_nscap(mnt_userns, dentry, &value, size); 303 302 if (error < 0) 304 303 return error; 305 304 size = error; 306 305 } 307 - 308 - if (size && is_posix_acl_xattr(name)) 309 - posix_acl_setxattr_idmapped_mnt(mnt_userns, inode, value, size); 310 306 311 307 retry_deleg: 312 308 inode_lock(inode); ··· 583 587 static void setxattr_convert(struct user_namespace *mnt_userns, 584 588 struct dentry *d, struct xattr_ctx *ctx) 585 589 { 586 - if (ctx->size && 587 - ((strcmp(ctx->kname->name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || 588 - (strcmp(ctx->kname->name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))) 590 + if (ctx->size && is_posix_acl_xattr(ctx->kname->name)) 589 591 posix_acl_fix_xattr_from_user(ctx->kvalue, ctx->size); 590 592 } 591 593 ··· 699 705 700 706 error = vfs_getxattr(mnt_userns, d, kname, ctx->kvalue, ctx->size); 701 707 if (error > 0) { 702 - if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || 703 - (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) 708 + if (is_posix_acl_xattr(kname)) 704 709 posix_acl_fix_xattr_to_user(ctx->kvalue, error); 705 710 if (ctx->size && copy_to_user(ctx->value, ctx->kvalue, error)) 706 711 error = -EFAULT;
+3 -9
include/linux/posix_acl_xattr.h
··· 38 38 void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns, 39 39 const struct inode *inode, 40 40 void *value, size_t size); 41 - void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns, 42 - const struct inode *inode, 43 - void *value, size_t size); 44 41 #else 45 42 static inline void posix_acl_fix_xattr_from_user(void *value, size_t size) 46 43 { ··· 51 54 size_t size) 52 55 { 53 56 } 54 - static inline void 55 - posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns, 56 - const struct inode *inode, void *value, 57 - size_t size) 58 - { 59 - } 60 57 #endif 61 58 62 59 struct posix_acl *posix_acl_from_xattr(struct user_namespace *user_ns, 63 60 const void *value, size_t size); 64 61 int posix_acl_to_xattr(struct user_namespace *user_ns, 65 62 const struct posix_acl *acl, void *buffer, size_t size); 63 + struct posix_acl *vfs_set_acl_prepare(struct user_namespace *mnt_userns, 64 + struct user_namespace *fs_userns, 65 + const void *value, size_t size); 66 66 67 67 extern const struct xattr_handler posix_acl_access_xattr_handler; 68 68 extern const struct xattr_handler posix_acl_default_xattr_handler;
+1 -1
include/linux/xattr.h
··· 61 61 const char *, const void *, size_t, int, 62 62 struct inode **); 63 63 int vfs_setxattr(struct user_namespace *, struct dentry *, const char *, 64 - void *, size_t, int); 64 + const void *, size_t, int); 65 65 int __vfs_removexattr(struct user_namespace *, struct dentry *, const char *); 66 66 int __vfs_removexattr_locked(struct user_namespace *, struct dentry *, 67 67 const char *, struct inode **);
+14 -3
security/integrity/evm/evm_main.c
··· 457 457 int rc; 458 458 459 459 /* 460 - * user_ns is not relevant here, ACL_USER/ACL_GROUP don't have impact 461 - * on the inode mode (see posix_acl_equiv_mode()). 460 + * An earlier comment here mentioned that the idmappings for 461 + * ACL_{GROUP,USER} don't matter since EVM is only interested in the 462 + * mode stored as part of POSIX ACLs. Nonetheless, if it must translate 463 + * from the uapi POSIX ACL representation to the VFS internal POSIX ACL 464 + * representation it should do so correctly. There's no guarantee that 465 + * we won't change POSIX ACLs in a way that ACL_{GROUP,USER} matters 466 + * for the mode at some point and it's difficult to keep track of all 467 + * the LSM and integrity modules and what they do to POSIX ACLs. 468 + * 469 + * Frankly, EVM shouldn't try to interpret the uapi struct for POSIX 470 + * ACLs it received. It requires knowledge that only the VFS is 471 + * guaranteed to have. 462 472 */ 463 - acl = posix_acl_from_xattr(&init_user_ns, xattr_value, xattr_value_len); 473 + acl = vfs_set_acl_prepare(mnt_userns, i_user_ns(inode), 474 + xattr_value, xattr_value_len); 464 475 if (IS_ERR_OR_NULL(acl)) 465 476 return 1; 466 477