fs: port to iattr ownership update helpers
authorChristian Brauner <brauner@kernel.org>
Tue, 21 Jun 2022 14:14:51 +0000 (16:14 +0200)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Sun, 26 Jun 2022 16:18:55 +0000 (18:18 +0200)
Earlier we introduced new helpers to abstract ownership update and
remove code duplication. This converts all filesystems supporting
idmapped mounts to make use of these new helpers.

For now we always pass the initial idmapping which makes the idmapping
functions these helpers call nops.

This is done because we currently always pass the actual value to be
written to i_{g,u}id via struct iattr. While this allowed us to treat
the {g,u}id values in struct iattr as values that can be directly
written to inode->i_{g,u}id it also increases the potential for
confusion for filesystems.

Now that we are have dedicated types to prevent this confusion we will
ultimately only map the value from the idmapped mount into a filesystem
value that can be written to inode->i_{g,u}id when the filesystem
actually updates the inode. So pass down the initial idmapping until we
finished that conversion at which point we pass down the mount's
idmapping.

No functional changes intended.

Link: https://lore.kernel.org/r/20220621141454.2914719-6-brauner@kernel.org
Cc: Seth Forshee <sforshee@digitalocean.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
CC: linux-fsdevel@vger.kernel.org
Reviewed-by: Seth Forshee <sforshee@digitalocean.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
fs/attr.c
fs/ext2/inode.c
fs/ext4/inode.c
fs/f2fs/file.c
fs/quota/dquot.c
fs/xfs/xfs_iops.c
include/linux/quotaops.h
security/integrity/evm/evm_main.c

index dbe996b0dedfcf78a91c077b9ee51d132a73d8d1..2e180dd9460f943c1434d8872f4192f27ef85894 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -242,10 +242,8 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
 {
        unsigned int ia_valid = attr->ia_valid;
 
-       if (ia_valid & ATTR_UID)
-               inode->i_uid = attr->ia_uid;
-       if (ia_valid & ATTR_GID)
-               inode->i_gid = attr->ia_gid;
+       i_uid_update(&init_user_ns, attr, inode);
+       i_gid_update(&init_user_ns, attr, inode);
        if (ia_valid & ATTR_ATIME)
                inode->i_atime = attr->ia_atime;
        if (ia_valid & ATTR_MTIME)
index e6b932219803ed9984c08d656806c6242bb430f0..6dc66ab97d20042a395acfb71d51a651a9ca0873 100644 (file)
@@ -1684,8 +1684,8 @@ int ext2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                if (error)
                        return error;
        }
-       if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) ||
-           (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) {
+       if (i_uid_needs_update(&init_user_ns, iattr, inode) ||
+           i_gid_needs_update(&init_user_ns, iattr, inode)) {
                error = dquot_transfer(inode, iattr);
                if (error)
                        return error;
index 84c0eb55071d65621f0c2fe6590382908ee8d35b..05d932f81c5365ba92870a9a9faba7a6e4a5ab86 100644 (file)
@@ -5356,8 +5356,8 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                        return error;
        }
 
-       if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) ||
-           (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) {
+       if (i_uid_needs_update(&init_user_ns, attr, inode) ||
+           i_gid_needs_update(&init_user_ns, attr, inode)) {
                handle_t *handle;
 
                /* (user+group)*(old+new) structure, inode write (sb,
@@ -5383,10 +5383,8 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                }
                /* Update corresponding info in inode so that everything is in
                 * one transaction */
-               if (attr->ia_valid & ATTR_UID)
-                       inode->i_uid = attr->ia_uid;
-               if (attr->ia_valid & ATTR_GID)
-                       inode->i_gid = attr->ia_gid;
+               i_uid_update(&init_user_ns, attr, inode);
+               i_gid_update(&init_user_ns, attr, inode);
                error = ext4_mark_inode_dirty(handle, inode);
                ext4_journal_stop(handle);
                if (unlikely(error)) {
index bd14cef1b08fd2761b1bddd27f178abddc98a36e..a35d6b12bd636c1cf38f6466acaa898d4550ed3b 100644 (file)
@@ -861,10 +861,8 @@ static void __setattr_copy(struct user_namespace *mnt_userns,
 {
        unsigned int ia_valid = attr->ia_valid;
 
-       if (ia_valid & ATTR_UID)
-               inode->i_uid = attr->ia_uid;
-       if (ia_valid & ATTR_GID)
-               inode->i_gid = attr->ia_gid;
+       i_uid_update(&init_user_ns, attr, inode);
+       i_gid_update(&init_user_ns, attr, inode);
        if (ia_valid & ATTR_ATIME)
                inode->i_atime = attr->ia_atime;
        if (ia_valid & ATTR_MTIME)
@@ -922,10 +920,8 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                if (err)
                        return err;
        }
-       if ((attr->ia_valid & ATTR_UID &&
-               !uid_eq(attr->ia_uid, inode->i_uid)) ||
-               (attr->ia_valid & ATTR_GID &&
-               !gid_eq(attr->ia_gid, inode->i_gid))) {
+       if (i_uid_needs_update(&init_user_ns, attr, inode) ||
+           i_gid_needs_update(&init_user_ns, attr, inode)) {
                f2fs_lock_op(F2FS_I_SB(inode));
                err = dquot_transfer(inode, attr);
                if (err) {
@@ -938,10 +934,8 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                 * update uid/gid under lock_op(), so that dquot and inode can
                 * be updated atomically.
                 */
-               if (attr->ia_valid & ATTR_UID)
-                       inode->i_uid = attr->ia_uid;
-               if (attr->ia_valid & ATTR_GID)
-                       inode->i_gid = attr->ia_gid;
+               i_uid_update(&init_user_ns, attr, inode);
+               i_gid_update(&init_user_ns, attr, inode);
                f2fs_mark_inode_dirty_sync(inode, true);
                f2fs_unlock_op(F2FS_I_SB(inode));
        }
index 09d1307959d085720769839b95f5c99f0478de78..6cec2bfbf51b2d2e78034a1ff478c07a6f81b6d8 100644 (file)
@@ -2095,7 +2095,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        if (!dquot_active(inode))
                return 0;
 
-       if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)){
+       if (i_uid_needs_update(&init_user_ns, iattr, inode)) {
                dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
                if (IS_ERR(dquot)) {
                        if (PTR_ERR(dquot) != -ESRCH) {
@@ -2106,7 +2106,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
                }
                transfer_to[USRQUOTA] = dquot;
        }
-       if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid)){
+       if (i_gid_needs_update(&init_user_ns, iattr, inode)) {
                dquot = dqget(sb, make_kqid_gid(iattr->ia_gid));
                if (IS_ERR(dquot)) {
                        if (PTR_ERR(dquot) != -ESRCH) {
index 29f5b8b8aca69a0887fae8f961b208fcf308638e..31ec29565fb4f7af714e27c894fcb3e8b91f181d 100644 (file)
@@ -704,13 +704,13 @@ xfs_setattr_nonsize(
         * didn't have the inode locked, inode's dquot(s) would have changed
         * also.
         */
-       if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp) &&
-           !uid_eq(inode->i_uid, iattr->ia_uid)) {
+       if (XFS_IS_UQUOTA_ON(mp) &&
+           i_uid_needs_update(&init_user_ns, iattr, inode)) {
                ASSERT(udqp);
                old_udqp = xfs_qm_vop_chown(tp, ip, &ip->i_udquot, udqp);
        }
-       if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp) &&
-           !gid_eq(inode->i_gid, iattr->ia_gid)) {
+       if (XFS_IS_GQUOTA_ON(mp) &&
+           i_gid_needs_update(&init_user_ns, iattr, inode)) {
                ASSERT(xfs_has_pquotino(mp) || !XFS_IS_PQUOTA_ON(mp));
                ASSERT(gdqp);
                old_gdqp = xfs_qm_vop_chown(tp, ip, &ip->i_gdquot, gdqp);
index a0f6668924d3ef068635e54ceef71d59421fe099..61ee34861ca2a4c97d5f67e0ba74a80bd3cd477a 100644 (file)
@@ -22,9 +22,9 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
 /* i_mutex must being held */
 static inline bool is_quota_modification(struct inode *inode, struct iattr *ia)
 {
-       return (ia->ia_valid & ATTR_SIZE) ||
-               (ia->ia_valid & ATTR_UID && !uid_eq(ia->ia_uid, inode->i_uid)) ||
-               (ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid));
+       return ((ia->ia_valid & ATTR_SIZE) ||
+               i_uid_needs_update(&init_user_ns, ia, inode) ||
+               i_gid_needs_update(&init_user_ns, ia, inode));
 }
 
 #if defined(CONFIG_QUOTA)
index cc88f02c7562159c258e0de27dc5f4868144d8a1..bcde6bc2a2cefb875acab10a90b6c6077c24bab9 100644 (file)
@@ -760,8 +760,8 @@ static int evm_attr_change(struct dentry *dentry, struct iattr *attr)
        struct inode *inode = d_backing_inode(dentry);
        unsigned int ia_valid = attr->ia_valid;
 
-       if ((!(ia_valid & ATTR_UID) || uid_eq(attr->ia_uid, inode->i_uid)) &&
-           (!(ia_valid & ATTR_GID) || gid_eq(attr->ia_gid, inode->i_gid)) &&
+       if (!i_uid_needs_update(&init_user_ns, attr, inode) &&
+           !i_gid_needs_update(&init_user_ns, attr, inode) &&
            (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode))
                return 0;