]> Git Repo - linux.git/commitdiff
attr: port attribute changes to new types
authorChristian Brauner <[email protected]>
Tue, 21 Jun 2022 14:14:54 +0000 (16:14 +0200)
committerChristian Brauner (Microsoft) <[email protected]>
Sun, 26 Jun 2022 16:18:56 +0000 (18:18 +0200)
Now that we introduced new infrastructure to increase the type safety
for filesystems supporting idmapped mounts port the first part of the
vfs over to them.

This ports the attribute changes codepaths to rely on the new better
helpers using a dedicated type.

Before this change we used to take a shortcut and place the actual
values that would be written to inode->i_{g,u}id into struct iattr. This
had the advantage that we moved idmappings mostly out of the picture
early on but it made reasoning about changes more difficult than it
should be.

The filesystem was never explicitly told that it dealt with an idmapped
mount. The transition to the value that needed to be stored in
inode->i_{g,u}id appeared way too early and increased the probability of
bugs in various codepaths.

We know place the same value in struct iattr no matter if this is an
idmapped mount or not. The vfs will only deal with type safe
vfs{g,u}id_t. This makes it massively safer to perform permission checks
as the type will tell us what checks we need to perform and what helpers
we need to use.

Fileystems raising FS_ALLOW_IDMAP can't simply write ia_vfs{g,u}id to
inode->i_{g,u}id since they are different types. Instead they need to
use the dedicated vfs{g,u}id_to_k{g,u}id() helpers that map the
vfs{g,u}id into the filesystem.

The other nice effect is that filesystems like overlayfs don't need to
care about idmappings explicitly anymore and can simply set up struct
iattr accordingly directly.

Link: https://lore.kernel.org/lkml/CAHk-=win6+ahs1EwLkcq8apqLi_1wXFWbrPf340zYEhObpz4jA@mail.gmail.com
Link: https://lore.kernel.org/r/[email protected]
Cc: Seth Forshee <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: Aleksa Sarai <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Al Viro <[email protected]>
CC: [email protected]
Reviewed-by: Seth Forshee <[email protected]>
Signed-off-by: Christian Brauner (Microsoft) <[email protected]>
18 files changed:
fs/attr.c
fs/ext2/inode.c
fs/ext4/inode.c
fs/f2fs/file.c
fs/f2fs/recovery.c
fs/fat/file.c
fs/jfs/file.c
fs/ocfs2/file.c
fs/open.c
fs/overlayfs/copy_up.c
fs/overlayfs/overlayfs.h
fs/quota/dquot.c
fs/reiserfs/inode.c
fs/xfs/xfs_iops.c
fs/zonefs/super.c
include/linux/fs.h
include/linux/quotaops.h
security/integrity/evm/evm_main.c

index 88e2ca30d42e2bef15e1513b91d109fc84d0a940..1ba7ddef537f9974f32b9bc9e7786ba2dff17170 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
  * performed on the raw inode simply passs init_user_ns.
  */
 static bool chown_ok(struct user_namespace *mnt_userns,
-                    const struct inode *inode,
-                    kuid_t uid)
+                    const struct inode *inode, vfsuid_t ia_vfsuid)
 {
-       kuid_t kuid = i_uid_into_mnt(mnt_userns, inode);
-       if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, inode->i_uid))
+       vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
+       if (vfsuid_eq_kuid(vfsuid, current_fsuid()) &&
+           vfsuid_eq(ia_vfsuid, vfsuid))
                return true;
        if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
-       if (uid_eq(kuid, INVALID_UID) &&
+       if (!vfsuid_valid(vfsuid) &&
            ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN))
                return true;
        return false;
@@ -58,21 +58,19 @@ static bool chown_ok(struct user_namespace *mnt_userns,
  * performed on the raw inode simply passs init_user_ns.
  */
 static bool chgrp_ok(struct user_namespace *mnt_userns,
-                    const struct inode *inode, kgid_t gid)
+                    const struct inode *inode, vfsgid_t ia_vfsgid)
 {
-       kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
-       if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) {
-               kgid_t mapped_gid;
-
-               if (gid_eq(gid, inode->i_gid))
+       vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
+       vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
+       if (vfsuid_eq_kuid(vfsuid, current_fsuid())) {
+               if (vfsgid_eq(ia_vfsgid, vfsgid))
                        return true;
-               mapped_gid = mapped_kgid_fs(mnt_userns, i_user_ns(inode), gid);
-               if (in_group_p(mapped_gid))
+               if (vfsgid_in_group_p(ia_vfsgid))
                        return true;
        }
        if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
-       if (gid_eq(kgid, INVALID_GID) &&
+       if (!vfsgid_valid(vfsgid) &&
            ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN))
                return true;
        return false;
@@ -120,28 +118,29 @@ int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
                goto kill_priv;
 
        /* Make sure a caller can chown. */
-       if ((ia_valid & ATTR_UID) && !chown_ok(mnt_userns, inode, attr->ia_uid))
+       if ((ia_valid & ATTR_UID) &&
+           !chown_ok(mnt_userns, inode, attr->ia_vfsuid))
                return -EPERM;
 
        /* Make sure caller can chgrp. */
-       if ((ia_valid & ATTR_GID) && !chgrp_ok(mnt_userns, inode, attr->ia_gid))
+       if ((ia_valid & ATTR_GID) &&
+           !chgrp_ok(mnt_userns, inode, attr->ia_vfsgid))
                return -EPERM;
 
        /* Make sure a caller can chmod. */
        if (ia_valid & ATTR_MODE) {
-               kgid_t mapped_gid;
+               vfsgid_t vfsgid;
 
                if (!inode_owner_or_capable(mnt_userns, inode))
                        return -EPERM;
 
                if (ia_valid & ATTR_GID)
-                       mapped_gid = mapped_kgid_fs(mnt_userns,
-                                               i_user_ns(inode), attr->ia_gid);
+                       vfsgid = attr->ia_vfsgid;
                else
-                       mapped_gid = i_gid_into_mnt(mnt_userns, inode);
+                       vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
 
                /* Also check the setgid bit! */
-               if (!in_group_p(mapped_gid) &&
+               if (!vfsgid_in_group_p(vfsgid) &&
                    !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
                        attr->ia_mode &= ~S_ISGID;
        }
@@ -219,9 +218,7 @@ EXPORT_SYMBOL(inode_newsize_ok);
  * setattr_copy must be called with i_mutex held.
  *
  * setattr_copy updates the inode's metadata with that specified
- * in attr on idmapped mounts. If file ownership is changed setattr_copy
- * doesn't map ia_uid and ia_gid. It will asssume the caller has already
- * provided the intended values. Necessary permission checks to determine
+ * in attr on idmapped mounts. Necessary permission checks to determine
  * whether or not the S_ISGID property needs to be removed are performed with
  * the correct idmapped mount permission helpers.
  * Noticeably missing is inode size update, which is more complex
@@ -242,8 +239,8 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
 {
        unsigned int ia_valid = attr->ia_valid;
 
-       i_uid_update(&init_user_ns, attr, inode);
-       i_gid_update(&init_user_ns, attr, inode);
+       i_uid_update(mnt_userns, attr, inode);
+       i_gid_update(mnt_userns, attr, inode);
        if (ia_valid & ATTR_ATIME)
                inode->i_atime = attr->ia_atime;
        if (ia_valid & ATTR_MTIME)
@@ -252,8 +249,8 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
                inode->i_ctime = attr->ia_ctime;
        if (ia_valid & ATTR_MODE) {
                umode_t mode = attr->ia_mode;
-               kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
-               if (!in_group_p(kgid) &&
+               vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
+               if (!vfsgid_in_group_p(vfsgid) &&
                    !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
                        mode &= ~S_ISGID;
                inode->i_mode = mode;
@@ -304,9 +301,6 @@ EXPORT_SYMBOL(may_setattr);
  * retry.  Because breaking a delegation may take a long time, the
  * caller should drop the i_mutex before doing so.
  *
- * If file ownership is changed notify_change() doesn't map ia_uid and
- * ia_gid. It will asssume the caller has already provided the intended values.
- *
  * Alternatively, a caller may pass NULL for delegated_inode.  This may
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.  Also, passing NULL is fine for callers holding
@@ -395,23 +389,25 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
         * namespace of the superblock.
         */
        if (ia_valid & ATTR_UID &&
-           !kuid_has_mapping(inode->i_sb->s_user_ns, attr->ia_uid))
+           !vfsuid_has_fsmapping(mnt_userns, inode->i_sb->s_user_ns,
+                                 attr->ia_vfsuid))
                return -EOVERFLOW;
        if (ia_valid & ATTR_GID &&
-           !kgid_has_mapping(inode->i_sb->s_user_ns, attr->ia_gid))
+           !vfsgid_has_fsmapping(mnt_userns, inode->i_sb->s_user_ns,
+                                 attr->ia_vfsgid))
                return -EOVERFLOW;
 
        /* Don't allow modifications of files with invalid uids or
         * gids unless those uids & gids are being made valid.
         */
        if (!(ia_valid & ATTR_UID) &&
-           !uid_valid(i_uid_into_mnt(mnt_userns, inode)))
+           !vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)))
                return -EOVERFLOW;
        if (!(ia_valid & ATTR_GID) &&
-           !gid_valid(i_gid_into_mnt(mnt_userns, inode)))
+           !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode)))
                return -EOVERFLOW;
 
-       error = security_inode_setattr(&init_user_ns, dentry, attr);
+       error = security_inode_setattr(mnt_userns, dentry, attr);
        if (error)
                return error;
        error = try_break_deleg(inode, delegated_inode);
index 593b79416e0eefa66e9c2f2d85d07680aa45e59a..7a192e4e7fa93551f2fd5e731056021623299230 100644 (file)
@@ -1679,14 +1679,14 @@ int ext2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (error)
                return error;
 
-       if (is_quota_modification(&init_user_ns, inode, iattr)) {
+       if (is_quota_modification(mnt_userns, inode, iattr)) {
                error = dquot_initialize(inode);
                if (error)
                        return error;
        }
-       if (i_uid_needs_update(&init_user_ns, iattr, inode) ||
-           i_gid_needs_update(&init_user_ns, iattr, inode)) {
-               error = dquot_transfer(&init_user_ns, inode, iattr);
+       if (i_uid_needs_update(mnt_userns, iattr, inode) ||
+           i_gid_needs_update(mnt_userns, iattr, inode)) {
+               error = dquot_transfer(mnt_userns, inode, iattr);
                if (error)
                        return error;
        }
index 72f08c184768c38808ce54844a75848271314fb8..3dcc1dd1f1799e09d1b7c7e2a4867b8d4d9e12ad 100644 (file)
@@ -5350,14 +5350,14 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (error)
                return error;
 
-       if (is_quota_modification(&init_user_ns, inode, attr)) {
+       if (is_quota_modification(mnt_userns, inode, attr)) {
                error = dquot_initialize(inode);
                if (error)
                        return error;
        }
 
-       if (i_uid_needs_update(&init_user_ns, attr, inode) ||
-           i_gid_needs_update(&init_user_ns, attr, inode)) {
+       if (i_uid_needs_update(mnt_userns, attr, inode) ||
+           i_gid_needs_update(mnt_userns, attr, inode)) {
                handle_t *handle;
 
                /* (user+group)*(old+new) structure, inode write (sb,
@@ -5374,7 +5374,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                 * counts xattr inode references.
                 */
                down_read(&EXT4_I(inode)->xattr_sem);
-               error = dquot_transfer(&init_user_ns, inode, attr);
+               error = dquot_transfer(mnt_userns, inode, attr);
                up_read(&EXT4_I(inode)->xattr_sem);
 
                if (error) {
@@ -5383,8 +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 */
-               i_uid_update(&init_user_ns, attr, inode);
-               i_gid_update(&init_user_ns, attr, inode);
+               i_uid_update(mnt_userns, attr, inode);
+               i_gid_update(mnt_userns, attr, inode);
                error = ext4_mark_inode_dirty(handle, inode);
                ext4_journal_stop(handle);
                if (unlikely(error)) {
index 02b2d56d4edc7b4fb6ec188491766fe1b499c791..d66e37d80a2da52fb49e1c6461dfb4c7417d5898 100644 (file)
@@ -861,8 +861,8 @@ static void __setattr_copy(struct user_namespace *mnt_userns,
 {
        unsigned int ia_valid = attr->ia_valid;
 
-       i_uid_update(&init_user_ns, attr, inode);
-       i_gid_update(&init_user_ns, attr, inode);
+       i_uid_update(mnt_userns, attr, inode);
+       i_gid_update(mnt_userns, attr, inode);
        if (ia_valid & ATTR_ATIME)
                inode->i_atime = attr->ia_atime;
        if (ia_valid & ATTR_MTIME)
@@ -915,15 +915,15 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (err)
                return err;
 
-       if (is_quota_modification(&init_user_ns, inode, attr)) {
+       if (is_quota_modification(mnt_userns, inode, attr)) {
                err = f2fs_dquot_initialize(inode);
                if (err)
                        return err;
        }
-       if (i_uid_needs_update(&init_user_ns, attr, inode) ||
-           i_gid_needs_update(&init_user_ns, attr, inode)) {
+       if (i_uid_needs_update(mnt_userns, attr, inode) ||
+           i_gid_needs_update(mnt_userns, attr, inode)) {
                f2fs_lock_op(F2FS_I_SB(inode));
-               err = dquot_transfer(&init_user_ns, inode, attr);
+               err = dquot_transfer(mnt_userns, inode, attr);
                if (err) {
                        set_sbi_flag(F2FS_I_SB(inode),
                                        SBI_QUOTA_NEED_REPAIR);
@@ -934,8 +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.
                 */
-               i_uid_update(&init_user_ns, attr, inode);
-               i_gid_update(&init_user_ns, attr, inode);
+               i_uid_update(mnt_userns, attr, inode);
+               i_gid_update(mnt_userns, attr, inode);
                f2fs_mark_inode_dirty_sync(inode, true);
                f2fs_unlock_op(F2FS_I_SB(inode));
        }
index 8e5a089f1ac88c855447320572d89ab8634a6dfa..dcd0a1e35095175178dff56c7b1f48e9d2fce680 100644 (file)
@@ -255,12 +255,12 @@ static int recover_quota_data(struct inode *inode, struct page *page)
 
        memset(&attr, 0, sizeof(attr));
 
-       attr.ia_uid = make_kuid(inode->i_sb->s_user_ns, i_uid);
-       attr.ia_gid = make_kgid(inode->i_sb->s_user_ns, i_gid);
+       attr.ia_vfsuid = VFSUIDT_INIT(make_kuid(inode->i_sb->s_user_ns, i_uid));
+       attr.ia_vfsgid = VFSGIDT_INIT(make_kgid(inode->i_sb->s_user_ns, i_gid));
 
-       if (!uid_eq(attr.ia_uid, inode->i_uid))
+       if (!vfsuid_eq(attr.ia_vfsuid, i_uid_into_vfsuid(&init_user_ns, inode)))
                attr.ia_valid |= ATTR_UID;
-       if (!gid_eq(attr.ia_gid, inode->i_gid))
+       if (!vfsgid_eq(attr.ia_vfsgid, i_gid_into_vfsgid(&init_user_ns, inode)))
                attr.ia_valid |= ATTR_GID;
 
        if (!attr.ia_valid)
index 530f18173db223d1790649c0d9aec88775a16721..3e4eb3467cb44beb276b91f82dded1fe1d0ad331 100644 (file)
@@ -90,7 +90,7 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
         * out the RO attribute for checking by the security
         * module, just because it maps to a file mode.
         */
-       err = security_inode_setattr(&init_user_ns,
+       err = security_inode_setattr(file_mnt_user_ns(file),
                                     file->f_path.dentry, &ia);
        if (err)
                goto out_unlock_inode;
@@ -517,9 +517,11 @@ int fat_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        }
 
        if (((attr->ia_valid & ATTR_UID) &&
-            (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
+            (!uid_eq(from_vfsuid(mnt_userns, i_user_ns(inode), attr->ia_vfsuid),
+                     sbi->options.fs_uid))) ||
            ((attr->ia_valid & ATTR_GID) &&
-            (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||
+            (!gid_eq(from_vfsgid(mnt_userns, i_user_ns(inode), attr->ia_vfsgid),
+                     sbi->options.fs_gid))) ||
            ((attr->ia_valid & ATTR_MODE) &&
             (attr->ia_mode & ~FAT_VALID_MODE)))
                error = -EPERM;
index c18569b9895d33179595d533d1e0005ff7d9c9c4..332dc9ac47a9161856a884ca9f782076d8fe0e45 100644 (file)
@@ -95,14 +95,14 @@ int jfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (rc)
                return rc;
 
-       if (is_quota_modification(&init_user_ns, inode, iattr)) {
+       if (is_quota_modification(mnt_userns, inode, iattr)) {
                rc = dquot_initialize(inode);
                if (rc)
                        return rc;
        }
        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))) {
-               rc = dquot_transfer(&init_user_ns, inode, iattr);
+               rc = dquot_transfer(mnt_userns, inode, iattr);
                if (rc)
                        return rc;
        }
index 0e09cd8911da409ca330a85d6b9781f05d6fa81e..9c67edd215d5ae70c50827ec6d6cc11527cac1ff 100644 (file)
@@ -1146,7 +1146,7 @@ int ocfs2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (status)
                return status;
 
-       if (is_quota_modification(&init_user_ns, inode, attr)) {
+       if (is_quota_modification(mnt_userns, inode, attr)) {
                status = dquot_initialize(inode);
                if (status)
                        return status;
index 1d57fbde2feb1c27e7bd059731abb31477eb6ba4..2790aac66e58e05095d6ce88de2d4edfd521460b 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -663,6 +663,42 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
        return do_fchmodat(AT_FDCWD, filename, mode);
 }
 
+/**
+ * setattr_vfsuid - check and set ia_fsuid attribute
+ * @kuid: new inode owner
+ *
+ * Check whether @kuid is valid and if so generate and set vfsuid_t in
+ * ia_vfsuid.
+ *
+ * Return: true if @kuid is valid, false if not.
+ */
+static inline bool setattr_vfsuid(struct iattr *attr, kuid_t kuid)
+{
+       if (!uid_valid(kuid))
+               return false;
+       attr->ia_valid |= ATTR_UID;
+       attr->ia_vfsuid = VFSUIDT_INIT(kuid);
+       return true;
+}
+
+/**
+ * setattr_vfsgid - check and set ia_fsgid attribute
+ * @kgid: new inode owner
+ *
+ * Check whether @kgid is valid and if so generate and set vfsgid_t in
+ * ia_vfsgid.
+ *
+ * Return: true if @kgid is valid, false if not.
+ */
+static inline bool setattr_vfsgid(struct iattr *attr, kgid_t kgid)
+{
+       if (!gid_valid(kgid))
+               return false;
+       attr->ia_valid |= ATTR_GID;
+       attr->ia_vfsgid = VFSGIDT_INIT(kgid);
+       return true;
+}
+
 int chown_common(const struct path *path, uid_t user, gid_t group)
 {
        struct user_namespace *mnt_userns, *fs_userns;
@@ -678,28 +714,22 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
 
        mnt_userns = mnt_user_ns(path->mnt);
        fs_userns = i_user_ns(inode);
-       uid = mapped_kuid_user(mnt_userns, fs_userns, uid);
-       gid = mapped_kgid_user(mnt_userns, fs_userns, gid);
 
 retry_deleg:
        newattrs.ia_valid =  ATTR_CTIME;
-       if (user != (uid_t) -1) {
-               if (!uid_valid(uid))
-                       return -EINVAL;
-               newattrs.ia_valid |= ATTR_UID;
-               newattrs.ia_uid = uid;
-       }
-       if (group != (gid_t) -1) {
-               if (!gid_valid(gid))
-                       return -EINVAL;
-               newattrs.ia_valid |= ATTR_GID;
-               newattrs.ia_gid = gid;
-       }
+       if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
+               return -EINVAL;
+       if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
+               return -EINVAL;
        if (!S_ISDIR(inode->i_mode))
                newattrs.ia_valid |=
                        ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
        inode_lock(inode);
-       error = security_path_chown(path, uid, gid);
+       /* Continue to send actual fs values, not the mount values. */
+       error = security_path_chown(
+               path,
+               from_vfsuid(mnt_userns, fs_userns, newattrs.ia_vfsuid),
+               from_vfsgid(mnt_userns, fs_userns, newattrs.ia_vfsgid));
        if (!error)
                error = notify_change(mnt_userns, path->dentry, &newattrs,
                                      &delegated_inode);
index 714ec569d25b31129831418d5f58a1d525580e0f..245e2cb627080d32d3af6e71aa9a8050de8b907d 100644 (file)
@@ -331,8 +331,8 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
        if (!err) {
                struct iattr attr = {
                        .ia_valid = ATTR_UID | ATTR_GID,
-                       .ia_uid = stat->uid,
-                       .ia_gid = stat->gid,
+                       .ia_vfsuid = VFSUIDT_INIT(stat->uid),
+                       .ia_vfsgid = VFSGIDT_INIT(stat->gid),
                };
                err = ovl_do_notify_change(ofs, upperdentry, &attr);
        }
index 4f34b7e02eeeb5659345c7929afa147646a4f594..e22e20f4811aa96692e8f2c859c2cb063e7c3ce1 100644 (file)
@@ -139,17 +139,7 @@ static inline int ovl_do_notify_change(struct ovl_fs *ofs,
                                       struct dentry *upperdentry,
                                       struct iattr *attr)
 {
-       struct user_namespace *upper_mnt_userns = ovl_upper_mnt_userns(ofs);
-       struct user_namespace *fs_userns = i_user_ns(d_inode(upperdentry));
-
-       if (attr->ia_valid & ATTR_UID)
-               attr->ia_uid = mapped_kuid_user(upper_mnt_userns,
-                                               fs_userns, attr->ia_uid);
-       if (attr->ia_valid & ATTR_GID)
-               attr->ia_gid = mapped_kgid_user(upper_mnt_userns,
-                                               fs_userns, attr->ia_gid);
-
-       return notify_change(upper_mnt_userns, upperdentry, attr, NULL);
+       return notify_change(ovl_upper_mnt_userns(ofs), upperdentry, attr, NULL);
 }
 
 static inline int ovl_do_rmdir(struct ovl_fs *ofs,
index df9af1ce2851d051f50e59a0aa74302f6e07d659..28966da7834ea254d1c23e3526917520b388b570 100644 (file)
@@ -2096,8 +2096,11 @@ int dquot_transfer(struct user_namespace *mnt_userns, struct inode *inode,
        if (!dquot_active(inode))
                return 0;
 
-       if (i_uid_needs_update(&init_user_ns, iattr, inode)) {
-               dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
+       if (i_uid_needs_update(mnt_userns, iattr, inode)) {
+               kuid_t kuid = from_vfsuid(mnt_userns, i_user_ns(inode),
+                                         iattr->ia_vfsuid);
+
+               dquot = dqget(sb, make_kqid_uid(kuid));
                if (IS_ERR(dquot)) {
                        if (PTR_ERR(dquot) != -ESRCH) {
                                ret = PTR_ERR(dquot);
@@ -2107,8 +2110,11 @@ int dquot_transfer(struct user_namespace *mnt_userns, struct inode *inode,
                }
                transfer_to[USRQUOTA] = dquot;
        }
-       if (i_gid_needs_update(&init_user_ns, iattr, inode)) {
-               dquot = dqget(sb, make_kqid_gid(iattr->ia_gid));
+       if (i_gid_needs_update(mnt_userns, iattr, inode)) {
+               kgid_t kgid = from_vfsgid(mnt_userns, i_user_ns(inode),
+                                         iattr->ia_vfsgid);
+
+               dquot = dqget(sb, make_kqid_gid(kgid));
                if (IS_ERR(dquot)) {
                        if (PTR_ERR(dquot) != -ESRCH) {
                                ret = PTR_ERR(dquot);
index 1e89e76972a042b138524900675e34ff36124b60..1141053b96ed5d060d66c890894badd353747b61 100644 (file)
@@ -3284,7 +3284,7 @@ int reiserfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       if (is_quota_modification(&init_user_ns, inode, attr)) {
+       if (is_quota_modification(mnt_userns, inode, attr)) {
                error = dquot_initialize(inode);
                if (error)
                        return error;
@@ -3367,7 +3367,7 @@ int reiserfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                reiserfs_write_unlock(inode->i_sb);
                if (error)
                        goto out;
-               error = dquot_transfer(&init_user_ns, inode, attr);
+               error = dquot_transfer(mnt_userns, inode, attr);
                reiserfs_write_lock(inode->i_sb);
                if (error) {
                        journal_end(&th);
index 31ec29565fb4f7af714e27c894fcb3e8b91f181d..a7402f6ea510406b4787570904e637e00f9cd899 100644 (file)
@@ -667,13 +667,15 @@ xfs_setattr_nonsize(
                uint    qflags = 0;
 
                if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp)) {
-                       uid = iattr->ia_uid;
+                       uid = from_vfsuid(mnt_userns, i_user_ns(inode),
+                                         iattr->ia_vfsuid);
                        qflags |= XFS_QMOPT_UQUOTA;
                } else {
                        uid = inode->i_uid;
                }
                if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp)) {
-                       gid = iattr->ia_gid;
+                       gid = from_vfsgid(mnt_userns, i_user_ns(inode),
+                                         iattr->ia_vfsgid);
                        qflags |= XFS_QMOPT_GQUOTA;
                }  else {
                        gid = inode->i_gid;
@@ -705,12 +707,12 @@ xfs_setattr_nonsize(
         * also.
         */
        if (XFS_IS_UQUOTA_ON(mp) &&
-           i_uid_needs_update(&init_user_ns, iattr, inode)) {
+           i_uid_needs_update(mnt_userns, iattr, inode)) {
                ASSERT(udqp);
                old_udqp = xfs_qm_vop_chown(tp, ip, &ip->i_udquot, udqp);
        }
        if (XFS_IS_GQUOTA_ON(mp) &&
-           i_gid_needs_update(&init_user_ns, iattr, inode)) {
+           i_gid_needs_update(mnt_userns, 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 dd422b1d73201144c7764fef0dc7c7ed184f8646..f5d8338967cb27e62500211350dcdee2f683e86c 100644 (file)
@@ -616,7 +616,7 @@ static int zonefs_inode_setattr(struct user_namespace *mnt_userns,
             !uid_eq(iattr->ia_uid, inode->i_uid)) ||
            ((iattr->ia_valid & ATTR_GID) &&
             !gid_eq(iattr->ia_gid, inode->i_gid))) {
-               ret = dquot_transfer(&init_user_ns, inode, iattr);
+               ret = dquot_transfer(mnt_userns, inode, iattr);
                if (ret)
                        return ret;
        }
index 0f8cc7f2665add041f354a448eb901120f7b5702..d6e3347cbf6928822a7852bd81298b969133afe9 100644 (file)
@@ -228,6 +228,10 @@ struct iattr {
         * are a dedicated type requiring the filesystem to use the dedicated
         * helpers. Other filesystem can continue to use ia_{g,u}id until they
         * have been ported.
+        *
+        * They always contain the same value. In other words FS_ALLOW_IDMAP
+        * pass down the same value on idmapped mounts as they would on regular
+        * mounts.
         */
        union {
                kuid_t          ia_uid;
index 0342ff6584fddfbc234df3f5cef6b8b50b9e4ab7..0d8625d717339ebbbe4c6d990cbb1680330e0288 100644 (file)
@@ -24,8 +24,8 @@ static inline bool is_quota_modification(struct user_namespace *mnt_userns,
                                         struct inode *inode, struct iattr *ia)
 {
        return ((ia->ia_valid & ATTR_SIZE) ||
-               i_uid_needs_update(&init_user_ns, ia, inode) ||
-               i_gid_needs_update(&init_user_ns, ia, inode));
+               i_uid_needs_update(mnt_userns, ia, inode) ||
+               i_gid_needs_update(mnt_userns, ia, inode));
 }
 
 #if defined(CONFIG_QUOTA)
index 7f4af5b5858317d1e68793618744fff9d2b2bf10..93e8bc047a736f4658e84c08b57125a5910b0c88 100644 (file)
@@ -761,8 +761,8 @@ static int evm_attr_change(struct user_namespace *mnt_userns,
        struct inode *inode = d_backing_inode(dentry);
        unsigned int ia_valid = attr->ia_valid;
 
-       if (!i_uid_needs_update(&init_user_ns, attr, inode) &&
-           !i_gid_needs_update(&init_user_ns, attr, inode) &&
+       if (!i_uid_needs_update(mnt_userns, attr, inode) &&
+           !i_gid_needs_update(mnt_userns, attr, inode) &&
            (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode))
                return 0;
 
This page took 0.126447 seconds and 4 git commands to generate.