attr: handle idmapped mounts
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 21 Jan 2021 13:19:26 +0000 (14:19 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sun, 24 Jan 2021 13:27:16 +0000 (14:27 +0100)
When file attributes are changed most filesystems rely on the
setattr_prepare(), setattr_copy(), and notify_change() helpers for
initialization and permission checking. Let them handle idmapped mounts.
If the inode is accessed through an idmapped mount map it into the
mount's user namespace. Afterwards the checks are identical to
non-idmapped mounts. If the initial user namespace is passed nothing
changes so non-idmapped mounts will see identical behavior as before.

Helpers that perform checks on the ia_uid and ia_gid fields in struct
iattr assume that ia_uid and ia_gid are intended values and have already
been mapped correctly at the userspace-kernelspace boundary as we
already do today. If the initial user namespace is passed nothing
changes so non-idmapped mounts will see identical behavior as before.

Link: https://lore.kernel.org/r/20210121131959.646623-8-christian.brauner@ubuntu.com
Cc: Christoph Hellwig <hch@lst.de>
Cc: David Howells <dhowells@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
57 files changed:
arch/powerpc/platforms/cell/spufs/inode.c
drivers/base/devtmpfs.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/adfs/inode.c
fs/affs/inode.c
fs/attr.c
fs/btrfs/inode.c
fs/cachefiles/interface.c
fs/ceph/inode.c
fs/cifs/inode.c
fs/ecryptfs/inode.c
fs/exfat/file.c
fs/ext2/inode.c
fs/ext4/inode.c
fs/f2fs/file.c
fs/fat/file.c
fs/fuse/dir.c
fs/gfs2/inode.c
fs/hfs/inode.c
fs/hfsplus/inode.c
fs/hostfs/hostfs_kern.c
fs/hpfs/inode.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/jffs2/fs.c
fs/jfs/file.c
fs/kernfs/inode.c
fs/libfs.c
fs/minix/file.c
fs/nfsd/nfsproc.c
fs/nfsd/vfs.c
fs/nilfs2/inode.c
fs/ntfs/inode.c
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/file.c
fs/omfs/file.c
fs/open.c
fs/orangefs/inode.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/super.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/proc_sysctl.c
fs/ramfs/file-nommu.c
fs/reiserfs/inode.c
fs/sysv/file.c
fs/ubifs/file.c
fs/udf/file.c
fs/ufs/inode.c
fs/utimes.c
fs/xfs/xfs_iops.c
fs/zonefs/super.c
include/linux/fs.h
mm/shmem.c

index 25390569e24cd8bf9e11a7d8202bc572670002fd..3de526eb22757024315dd28df500da2439d8f4da 100644 (file)
@@ -98,7 +98,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr)
        if ((attr->ia_valid & ATTR_SIZE) &&
            (attr->ia_size != inode->i_size))
                return -EINVAL;
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index eac184e6d65774da9a39cf70e6f71848a1a373d5..2e0c3cdb4184bcb2d00860cf774cf4092bff548e 100644 (file)
@@ -221,7 +221,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
                newattrs.ia_gid = gid;
                newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
                inode_lock(d_inode(dentry));
-               notify_change(dentry, &newattrs, NULL);
+               notify_change(&init_user_ns, dentry, &newattrs, NULL);
                inode_unlock(d_inode(dentry));
 
                /* mark as kernel-created inode */
@@ -328,7 +328,7 @@ static int handle_remove(const char *nodename, struct device *dev)
                        newattrs.ia_valid =
                                ATTR_UID|ATTR_GID|ATTR_MODE;
                        inode_lock(d_inode(dentry));
-                       notify_change(dentry, &newattrs, NULL);
+                       notify_change(&init_user_ns, dentry, &newattrs, NULL);
                        inode_unlock(d_inode(dentry));
                        err = vfs_unlink(d_inode(parent.dentry), dentry, NULL);
                        if (!err || err == -ENOENT)
index f66eb3c12c8adeb6e982ba9431738ba742d46b33..9c3ff6e9ab82b52623902a6b8d01039b39048bfb 100644 (file)
@@ -1062,7 +1062,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
        struct p9_wstat wstat;
 
        p9_debug(P9_DEBUG_VFS, "\n");
-       retval = setattr_prepare(dentry, iattr);
+       retval = setattr_prepare(&init_user_ns, dentry, iattr);
        if (retval)
                return retval;
 
@@ -1118,7 +1118,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 
        v9fs_invalidate_inode_attr(d_inode(dentry));
 
-       setattr_copy(d_inode(dentry), iattr);
+       setattr_copy(&init_user_ns, d_inode(dentry), iattr);
        mark_inode_dirty(d_inode(dentry));
        return 0;
 }
index 823c2eb5f1bf681a9c79a5f0f565da5989e0ef6a..302553101fcbf3659b2694b3ddd3185dc4403e54 100644 (file)
@@ -549,7 +549,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
 
        p9_debug(P9_DEBUG_VFS, "\n");
 
-       retval = setattr_prepare(dentry, iattr);
+       retval = setattr_prepare(&init_user_ns, dentry, iattr);
        if (retval)
                return retval;
 
@@ -590,7 +590,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
                truncate_setsize(inode, iattr->ia_size);
 
        v9fs_invalidate_inode_attr(inode);
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        mark_inode_dirty(inode);
        if (iattr->ia_valid & ATTR_MODE) {
                /* We also want to update ACL when we update mode bits */
index 32620f4a7623ecb5d2d166605ce536b0a3c5b11d..278dcee6ae225063648ab31bcc1444666f0911c0 100644 (file)
@@ -299,7 +299,7 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
        unsigned int ia_valid = attr->ia_valid;
        int error;
        
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
 
        /*
         * we can't change the UID or GID of any file -
index 044412110b52354f927a49603a6f164785cc8e8c..767e5bdfb7030353f0746be69be88d722a199afc 100644 (file)
@@ -223,7 +223,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
 
        pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                goto out;
 
@@ -249,7 +249,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
                affs_truncate(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
 
        if (attr->ia_valid & ATTR_MODE)
index 00ae0b000146f3b717dbfab56160b18129e91395..f4543d2abdfbd1ed516f90c671914a2f7652d8ba 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
 #include <linux/evm.h>
 #include <linux/ima.h>
 
-static bool chown_ok(const struct inode *inode, kuid_t uid)
+/**
+ * chown_ok - verify permissions to chown inode
+ * @mnt_userns:        user namespace of the mount @inode was found from
+ * @inode:     inode to check permissions on
+ * @uid:       uid to chown @inode to
+ *
+ * If the inode has been found through an idmapped mount the user namespace of
+ * the vfsmount must be passed through @mnt_userns. This function will then
+ * take care to map the inode according to @mnt_userns before checking
+ * permissions. On non-idmapped mounts or if permission checking is to be
+ * 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)
 {
-       if (uid_eq(current_fsuid(), inode->i_uid) &&
-           uid_eq(uid, inode->i_uid))
+       kuid_t kuid = i_uid_into_mnt(mnt_userns, inode);
+       if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, kuid))
                return true;
-       if (capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_CHOWN))
+       if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
-       if (uid_eq(inode->i_uid, INVALID_UID) &&
+       if (uid_eq(kuid, INVALID_UID) &&
            ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN))
                return true;
        return false;
 }
 
-static bool chgrp_ok(const struct inode *inode, kgid_t gid)
+/**
+ * chgrp_ok - verify permissions to chgrp inode
+ * @mnt_userns:        user namespace of the mount @inode was found from
+ * @inode:     inode to check permissions on
+ * @gid:       gid to chown @inode to
+ *
+ * If the inode has been found through an idmapped mount the user namespace of
+ * the vfsmount must be passed through @mnt_userns. This function will then
+ * take care to map the inode according to @mnt_userns before checking
+ * permissions. On non-idmapped mounts or if permission checking is to be
+ * 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)
 {
-       if (uid_eq(current_fsuid(), inode->i_uid) &&
-           (in_group_p(gid) || gid_eq(gid, inode->i_gid)))
+       kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
+       if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode)) &&
+           (in_group_p(gid) || gid_eq(gid, kgid)))
                return true;
-       if (capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_CHOWN))
+       if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
-       if (gid_eq(inode->i_gid, INVALID_GID) &&
+       if (gid_eq(kgid, INVALID_GID) &&
            ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN))
                return true;
        return false;
@@ -46,6 +74,7 @@ static bool chgrp_ok(const struct inode *inode, kgid_t gid)
 
 /**
  * setattr_prepare - check if attribute changes to a dentry are allowed
+ * @mnt_userns:        user namespace of the mount the inode was found from
  * @dentry:    dentry to check
  * @attr:      attributes to change
  *
@@ -55,10 +84,17 @@ static bool chgrp_ok(const struct inode *inode, kgid_t gid)
  * SGID bit from mode if user is not allowed to set it. Also file capabilities
  * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set.
  *
+ * If the inode has been found through an idmapped mount the user namespace of
+ * the vfsmount must be passed through @mnt_userns. This function will then
+ * take care to map the inode according to @mnt_userns before checking
+ * permissions. On non-idmapped mounts or if permission checking is to be
+ * performed on the raw inode simply passs init_user_ns.
+ *
  * Should be called as the first thing in ->setattr implementations,
  * possibly after taking additional locks.
  */
-int setattr_prepare(struct dentry *dentry, struct iattr *attr)
+int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
+                   struct iattr *attr)
 {
        struct inode *inode = d_inode(dentry);
        unsigned int ia_valid = attr->ia_valid;
@@ -78,27 +114,27 @@ int setattr_prepare(struct dentry *dentry, struct iattr *attr)
                goto kill_priv;
 
        /* Make sure a caller can chown. */
-       if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
+       if ((ia_valid & ATTR_UID) && !chown_ok(mnt_userns, inode, attr->ia_uid))
                return -EPERM;
 
        /* Make sure caller can chgrp. */
-       if ((ia_valid & ATTR_GID) && !chgrp_ok(inode, attr->ia_gid))
+       if ((ia_valid & ATTR_GID) && !chgrp_ok(mnt_userns, inode, attr->ia_gid))
                return -EPERM;
 
        /* Make sure a caller can chmod. */
        if (ia_valid & ATTR_MODE) {
-               if (!inode_owner_or_capable(&init_user_ns, inode))
+               if (!inode_owner_or_capable(mnt_userns, inode))
                        return -EPERM;
                /* Also check the setgid bit! */
-               if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
-                               inode->i_gid) &&
-                   !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
+               if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
+                                i_gid_into_mnt(mnt_userns, inode)) &&
+                    !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
                        attr->ia_mode &= ~S_ISGID;
        }
 
        /* Check for setting the inode time. */
        if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
-               if (!inode_owner_or_capable(&init_user_ns, inode))
+               if (!inode_owner_or_capable(mnt_userns, inode))
                        return -EPERM;
        }
 
@@ -162,20 +198,33 @@ EXPORT_SYMBOL(inode_newsize_ok);
 
 /**
  * setattr_copy - copy simple metadata updates into the generic inode
+ * @mnt_userns:        user namespace of the mount the inode was found from
  * @inode:     the inode to be updated
  * @attr:      the new attributes
  *
  * setattr_copy must be called with i_mutex held.
  *
  * setattr_copy updates the inode's metadata with that specified
- * in attr. Noticeably missing is inode size update, which is more complex
+ * 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
+ * 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
  * as it requires pagecache updates.
  *
+ * If the inode has been found through an idmapped mount the user namespace of
+ * the vfsmount must be passed through @mnt_userns. This function will then
+ * take care to map the inode according to @mnt_userns before checking
+ * permissions. On non-idmapped mounts or if permission checking is to be
+ * performed on the raw inode simply passs init_user_ns.
+ *
  * The inode is not marked as dirty after this operation. The rationale is
  * that for "simple" filesystems, the struct inode is the inode storage.
  * The caller is free to mark the inode dirty afterwards if needed.
  */
-void setattr_copy(struct inode *inode, const struct iattr *attr)
+void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
+                 const struct iattr *attr)
 {
        unsigned int ia_valid = attr->ia_valid;
 
@@ -191,9 +240,9 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
                inode->i_ctime = attr->ia_ctime;
        if (ia_valid & ATTR_MODE) {
                umode_t mode = attr->ia_mode;
-
-               if (!in_group_p(inode->i_gid) &&
-                   !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
+               kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
+               if (!in_group_p(kgid) &&
+                   !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
                        mode &= ~S_ISGID;
                inode->i_mode = mode;
        }
@@ -202,6 +251,7 @@ EXPORT_SYMBOL(setattr_copy);
 
 /**
  * notify_change - modify attributes of a filesytem object
+ * @mnt_userns:        user namespace of the mount the inode was found from
  * @dentry:    object affected
  * @attr:      new attributes
  * @delegated_inode: returns inode, if the inode is delegated
@@ -214,13 +264,23 @@ EXPORT_SYMBOL(setattr_copy);
  * 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
  * the file open for write, as there can be no conflicting delegation in
  * that case.
+ *
+ * If the inode has been found through an idmapped mount the user namespace of
+ * the vfsmount must be passed through @mnt_userns. This function will then
+ * take care to map the inode according to @mnt_userns before checking
+ * permissions. On non-idmapped mounts or if permission checking is to be
+ * performed on the raw inode simply passs init_user_ns.
  */
-int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
+int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
+                 struct iattr *attr, struct inode **delegated_inode)
 {
        struct inode *inode = dentry->d_inode;
        umode_t mode = inode->i_mode;
@@ -243,9 +303,8 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
                if (IS_IMMUTABLE(inode))
                        return -EPERM;
 
-               if (!inode_owner_or_capable(&init_user_ns, inode)) {
-                       error = inode_permission(&init_user_ns, inode,
-                                                MAY_WRITE);
+               if (!inode_owner_or_capable(mnt_userns, inode)) {
+                       error = inode_permission(mnt_userns, inode, MAY_WRITE);
                        if (error)
                                return error;
                }
@@ -321,9 +380,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
        /* 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(inode->i_uid))
+       if (!(ia_valid & ATTR_UID) &&
+           !uid_valid(i_uid_into_mnt(mnt_userns, inode)))
                return -EOVERFLOW;
-       if (!(ia_valid & ATTR_GID) && !gid_valid(inode->i_gid))
+       if (!(ia_valid & ATTR_GID) &&
+           !gid_valid(i_gid_into_mnt(mnt_userns, inode)))
                return -EOVERFLOW;
 
        error = security_inode_setattr(dentry, attr);
index 07fe8b2f3babd68a6cdf324f5dfaf31da04b9339..792191a8705b06eb5cf9f2d5af13883536b3654b 100644 (file)
@@ -5054,7 +5054,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
        if (btrfs_root_readonly(root))
                return -EROFS;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
 
@@ -5065,7 +5065,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        if (attr->ia_valid) {
-               setattr_copy(inode, attr);
+               setattr_copy(&init_user_ns, inode, attr);
                inode_inc_iversion(inode);
                err = btrfs_dirty_inode(inode);
 
index 4cea5fbf695ea349e9c16da21afeedcd27f32914..5efa6a3702c060feea6d3ef6b6297d76905355fa 100644 (file)
@@ -470,14 +470,14 @@ static int cachefiles_attr_changed(struct fscache_object *_object)
                _debug("discard tail %llx", oi_size);
                newattrs.ia_valid = ATTR_SIZE;
                newattrs.ia_size = oi_size & PAGE_MASK;
-               ret = notify_change(object->backer, &newattrs, NULL);
+               ret = notify_change(&init_user_ns, object->backer, &newattrs, NULL);
                if (ret < 0)
                        goto truncate_failed;
        }
 
        newattrs.ia_valid = ATTR_SIZE;
        newattrs.ia_size = ni_size;
-       ret = notify_change(object->backer, &newattrs, NULL);
+       ret = notify_change(&init_user_ns, object->backer, &newattrs, NULL);
 
 truncate_failed:
        inode_unlock(d_inode(object->backer));
index e8a15ee09bc1052421dd74b30d88238529d724d0..285d3baca27ef4c3d29ca7b4ac6ac8fa0fc0e049 100644 (file)
@@ -2247,7 +2247,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err != 0)
                return err;
 
index a83b3a8ffaacca690838f66fe4048efe89caf6db..27554f71f744cb679ba2406cbba6729882649328 100644 (file)
@@ -2610,7 +2610,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
                attrs->ia_valid |= ATTR_FORCE;
 
-       rc = setattr_prepare(direntry, attrs);
+       rc = setattr_prepare(&init_user_ns, direntry, attrs);
        if (rc < 0)
                goto out;
 
@@ -2715,7 +2715,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
            attrs->ia_size != i_size_read(inode))
                truncate_setsize(inode, attrs->ia_size);
 
-       setattr_copy(inode, attrs);
+       setattr_copy(&init_user_ns, inode, attrs);
        mark_inode_dirty(inode);
 
        /* force revalidate when any of these times are set since some
@@ -2757,7 +2757,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
                attrs->ia_valid |= ATTR_FORCE;
 
-       rc = setattr_prepare(direntry, attrs);
+       rc = setattr_prepare(&init_user_ns, direntry, attrs);
        if (rc < 0) {
                free_xid(xid);
                return rc;
@@ -2913,7 +2913,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
            attrs->ia_size != i_size_read(inode))
                truncate_setsize(inode, attrs->ia_size);
 
-       setattr_copy(inode, attrs);
+       setattr_copy(&init_user_ns, inode, attrs);
        mark_inode_dirty(inode);
 
 cifs_setattr_exit:
index 0b346baf110d79e7053b3d113879f698ea37545f..d3ea0c57b075de49b69bf6d6ea3a5da7513a5d51 100644 (file)
@@ -855,7 +855,8 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
                struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
 
                inode_lock(d_inode(lower_dentry));
-               rc = notify_change(lower_dentry, &lower_ia, NULL);
+               rc = notify_change(&init_user_ns, lower_dentry,
+                                  &lower_ia, NULL);
                inode_unlock(d_inode(lower_dentry));
        }
        return rc;
@@ -934,7 +935,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
        }
        mutex_unlock(&crypt_stat->cs_mutex);
 
-       rc = setattr_prepare(dentry, ia);
+       rc = setattr_prepare(&init_user_ns, dentry, ia);
        if (rc)
                goto out;
        if (ia->ia_valid & ATTR_SIZE) {
@@ -960,7 +961,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
                lower_ia.ia_valid &= ~ATTR_MODE;
 
        inode_lock(d_inode(lower_dentry));
-       rc = notify_change(lower_dentry, &lower_ia, NULL);
+       rc = notify_change(&init_user_ns, lower_dentry, &lower_ia, NULL);
        inode_unlock(d_inode(lower_dentry));
 out:
        fsstack_copy_attr_all(inode, lower_inode);
index a92478eabfa4e43f2198ccf9b62b8632b697c8dc..ace35aa8e64b7f416f26cfa194253d27389dfc7f 100644 (file)
@@ -305,7 +305,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
                                ATTR_TIMES_SET);
        }
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        attr->ia_valid = ia_valid;
        if (error)
                goto out;
@@ -340,7 +340,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
                up_write(&EXFAT_I(inode)->truncate_lock);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        exfat_truncate_atime(&inode->i_atime);
        mark_inode_dirty(inode);
 
index 78c417d3c8982cc004884afffac14d052f1cc120..06c0cf28c1a0fe4461da05dba982634ce1e3fecd 100644 (file)
@@ -1669,7 +1669,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
        struct inode *inode = d_inode(dentry);
        int error;
 
-       error = setattr_prepare(dentry, iattr);
+       error = setattr_prepare(&init_user_ns, dentry, iattr);
        if (error)
                return error;
 
@@ -1689,7 +1689,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
                if (error)
                        return error;
        }
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        if (iattr->ia_valid & ATTR_MODE)
                error = posix_acl_chmod(inode, inode->i_mode);
        mark_inode_dirty(inode);
index c173c840585618b0be404937154dd8516eccf60a..8edfa3e226e660339ac04ab39a0e1040df28eddc 100644 (file)
@@ -5337,7 +5337,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                                  ATTR_GID | ATTR_TIMES_SET))))
                return -EPERM;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -5512,7 +5512,7 @@ out_mmap_sem:
        }
 
        if (!error) {
-               setattr_copy(inode, attr);
+               setattr_copy(&init_user_ns, inode, attr);
                mark_inode_dirty(inode);
        }
 
index 5fc0ff28b5ddb560873545ab221547baa6626e5e..90d7b89176de8945124ba1f19dea21d91e03d0e2 100644 (file)
@@ -831,7 +831,8 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
 }
 
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
-static void __setattr_copy(struct inode *inode, const struct iattr *attr)
+static void __setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
+                          const struct iattr *attr)
 {
        unsigned int ia_valid = attr->ia_valid;
 
@@ -847,8 +848,9 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr)
                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(inode->i_gid) && !capable(CAP_FSETID))
+               if (!in_group_p(kgid) && !capable(CAP_FSETID))
                        mode &= ~S_ISGID;
                set_acl_inode(inode, mode);
        }
@@ -869,7 +871,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
                !f2fs_is_compress_backend_ready(inode))
                return -EOPNOTSUPP;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
 
@@ -945,7 +947,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
                spin_unlock(&F2FS_I(inode)->i_size_lock);
        }
 
-       __setattr_copy(inode, attr);
+       __setattr_copy(&init_user_ns, inode, attr);
 
        if (attr->ia_valid & ATTR_MODE) {
                err = posix_acl_chmod(inode, f2fs_get_inode_mode(inode));
index f9ee27cf4d7c2f678c67ba61f878d1494b315104..805b501467e9f75e3c5eda70a50af7b9b5f3f53b 100644 (file)
@@ -480,7 +480,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
                        attr->ia_valid &= ~TIMES_SET_FLAGS;
        }
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        attr->ia_valid = ia_valid;
        if (error) {
                if (sbi->options.quiet)
@@ -550,7 +550,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
                fat_truncate_time(inode, &attr->ia_mtime, S_MTIME);
        attr->ia_valid &= ~(ATTR_ATIME|ATTR_CTIME|ATTR_MTIME);
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
 out:
        return error;
index 7497009a5a453519fb4e07a5eb5dc3d0fb159f90..74fdb6a7ebb305e252d3d0e5bd1235ee2b109ff5 100644 (file)
@@ -1611,7 +1611,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
        if (!fc->default_permissions)
                attr->ia_valid |= ATTR_FORCE;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
 
index 5b2ff0c74b67b47ae926f7fcaf1b532398404300..59c25181d108fa049a23993b4216a9d9112f989c 100644 (file)
@@ -1861,7 +1861,7 @@ int gfs2_permission(struct inode *inode, int mask)
 
 static int __gfs2_setattr_simple(struct inode *inode, struct iattr *attr)
 {
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
@@ -1982,7 +1982,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                goto error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                goto error;
 
index f35a37c65e5fffb5a9b0bce1b85420a6d7de4a40..c646218b72bfa9d471f7ff7e7e5cbd2f212bf968 100644 (file)
@@ -608,7 +608,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
        int error;
 
-       error = setattr_prepare(dentry, attr); /* basic permission checks */
+       error = setattr_prepare(&init_user_ns, dentry, attr); /* basic permission checks */
        if (error)
                return error;
 
@@ -647,7 +647,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
                                                  current_time(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index 21357046b0396d949aee02db5aa57b3c0fdcd844..ffa137f8234eda94f614f7abcf674bd8076e25db 100644 (file)
@@ -246,7 +246,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
        struct inode *inode = d_inode(dentry);
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -264,7 +264,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
                inode->i_mtime = inode->i_ctime = current_time(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
 
        return 0;
index b841a05a2b8c9c552cf3a3f19bba5387ec9fab9a..6970e29a528790185db64cc997153ec7faf6c51c 100644 (file)
@@ -792,7 +792,7 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        int fd = HOSTFS_I(inode)->fd;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
 
@@ -849,7 +849,7 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
            attr->ia_size != i_size_read(inode))
                truncate_setsize(inode, attr->ia_size);
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index eb8b4baf0f2e0630d60a11cbac4d2efc976df209..8ba2152a78ba8f7d1bfd04e77c33499eca9e563a 100644 (file)
@@ -274,7 +274,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
        if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
                goto out_unlock;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                goto out_unlock;
 
@@ -288,7 +288,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
                hpfs_truncate(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
 
        hpfs_write_inode(inode);
 
index 6737929e443ca4bacdd45b7b504e02c313adb364..327e572b4e003dc634830e4d0c43cd8ac0edcb30 100644 (file)
@@ -761,7 +761,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        BUG_ON(!inode);
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -780,7 +780,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
                        return error;
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index a9ac97a2778487b872fe9c9560094857ff496b3e..49b512592dcd73ce471c3276eb73ef19b94002c8 100644 (file)
@@ -1912,7 +1912,7 @@ static int __remove_privs(struct dentry *dentry, int kill)
         * Note we call this on write, so notify_change will not
         * encounter any conflicting delegations:
         */
-       return notify_change(dentry, &newattrs, NULL);
+       return notify_change(&init_user_ns, dentry, &newattrs, NULL);
 }
 
 /*
index 78858f6e95839cb03859fd36d67dfd85d7c6ba74..67993808f4dafef6aa1d4f1ac2881c657b110ec4 100644 (file)
@@ -195,7 +195,7 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
        struct inode *inode = d_inode(dentry);
        int rc;
 
-       rc = setattr_prepare(dentry, iattr);
+       rc = setattr_prepare(&init_user_ns, dentry, iattr);
        if (rc)
                return rc;
 
index 930d2701f2062bc6801a6fdaf978742c679dc09e..ff49876e9c9b263014e3ae7cb477dbc45bc5fb20 100644 (file)
@@ -90,7 +90,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
        struct inode *inode = d_inode(dentry);
        int rc;
 
-       rc = setattr_prepare(dentry, iattr);
+       rc = setattr_prepare(&init_user_ns, dentry, iattr);
        if (rc)
                return rc;
 
@@ -118,7 +118,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
                jfs_truncate(inode);
        }
 
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        mark_inode_dirty(inode);
 
        if (iattr->ia_valid & ATTR_MODE)
index ff5598cc1de0f9b1427cc856b8733df8a4f7d67a..86bd4c593b78a0c352746f0e50fdcc9a18aaa23d 100644 (file)
@@ -122,7 +122,7 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
                return -EINVAL;
 
        mutex_lock(&kernfs_mutex);
-       error = setattr_prepare(dentry, iattr);
+       error = setattr_prepare(&init_user_ns, dentry, iattr);
        if (error)
                goto out;
 
@@ -131,7 +131,7 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
                goto out;
 
        /* this ignores size changes */
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
 
 out:
        mutex_unlock(&kernfs_mutex);
index f8b3c02b4f0f98c9da74e1f5194cc00873423e16..a73fe109403cbc2c979e951a2682eeaa81dc345e 100644 (file)
@@ -497,13 +497,13 @@ int simple_setattr(struct dentry *dentry, struct iattr *iattr)
        struct inode *inode = d_inode(dentry);
        int error;
 
-       error = setattr_prepare(dentry, iattr);
+       error = setattr_prepare(&init_user_ns, dentry, iattr);
        if (error)
                return error;
 
        if (iattr->ia_valid & ATTR_SIZE)
                truncate_setsize(inode, iattr->ia_size);
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        mark_inode_dirty(inode);
        return 0;
 }
index c50b0a20fcd9c15ecf4a2bd8887bce9a8b6e88f8..f07acd268577f8517bb0bd102e51d7104da5a548 100644 (file)
@@ -27,7 +27,7 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
        struct inode *inode = d_inode(dentry);
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -41,7 +41,7 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr)
                minix_truncate(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index 9473d048efec8fd4363b8f46b63a1443ec9b73ca..0ea0554d20d17c7333b1a2a4afbba0fc8c698860 100644 (file)
@@ -90,7 +90,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
                if (delta < 0)
                        delta = -delta;
                if (delta < MAX_TOUCH_TIME_ERROR &&
-                   setattr_prepare(fhp->fh_dentry, iap) != 0) {
+                   setattr_prepare(&init_user_ns, fhp->fh_dentry, iap) != 0) {
                        /*
                         * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
                         * This will cause notify_change to set these times
index 0edf11258aaa7329f637ed93b3b09e3125b56f39..1905b39be1c2c4e0c50bf4f8aa0bfc3bb9fd0a08 100644 (file)
@@ -448,7 +448,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
                        .ia_size        = iap->ia_size,
                };
 
-               host_err = notify_change(dentry, &size_attr, NULL);
+               host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL);
                if (host_err)
                        goto out_unlock;
                iap->ia_valid &= ~ATTR_SIZE;
@@ -463,7 +463,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        }
 
        iap->ia_valid |= ATTR_CTIME;
-       host_err = notify_change(dentry, iap, NULL);
+       host_err = notify_change(&init_user_ns, dentry, iap, NULL);
 
 out_unlock:
        fh_unlock(fhp);
index 11225a65973697402f08dfc68115cef1ea90cc13..8aad3c48092a63394144b02ce11776e11775e308 100644 (file)
@@ -812,7 +812,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
        struct super_block *sb = inode->i_sb;
        int err;
 
-       err = setattr_prepare(dentry, iattr);
+       err = setattr_prepare(&init_user_ns, dentry, iattr);
        if (err)
                return err;
 
@@ -827,7 +827,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
                nilfs_truncate(inode);
        }
 
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        mark_inode_dirty(inode);
 
        if (iattr->ia_valid & ATTR_MODE) {
index f7e4cbc26eaf954da7febc6164111377ea4e7015..38f4cf1d44977241724ec310d60ce46874d02f54 100644 (file)
@@ -2866,7 +2866,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
        int err;
        unsigned int ia_valid = attr->ia_valid;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                goto out;
        /* We do not support NTFS ACLs yet. */
index 37c7d03a6284a36a1633ebfec3b02bdfffb6cd28..9fa66cd1f622230042799694a4da7eae16da6579 100644 (file)
@@ -196,11 +196,11 @@ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
        struct inode *inode = d_inode(dentry);
 
        attr->ia_valid &= ~ATTR_SIZE;
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index 0c75619adf54676aa1b256774b16a90a013963cb..cabf355b148ff19e893c8afefe25bc2a2f1bb173 100644 (file)
@@ -1142,7 +1142,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
        if (!(attr->ia_valid & OCFS2_VALID_ATTRS))
                return 0;
 
-       status = setattr_prepare(dentry, attr);
+       status = setattr_prepare(&init_user_ns, dentry, attr);
        if (status)
                return status;
 
@@ -1263,7 +1263,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                }
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
 
        status = ocfs2_mark_inode_dirty(handle, inode, bh);
index 2c7b70ee1388c2b349775be5ca8e0e2f9c0450c3..729339cd79025ead0c357abdff8a1dd70d0c11ac 100644 (file)
@@ -348,7 +348,7 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
        struct inode *inode = d_inode(dentry);
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -361,7 +361,7 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
                omfs_truncate(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index a6dac6d97988a6abc3116ddaf0c2638c9e5d9751..c3e4dc43dd8dd3d62085ded92b742dcc148b69f6 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -61,7 +61,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 
        inode_lock(dentry->d_inode);
        /* Note any delegations or leases have already been broken: */
-       ret = notify_change(dentry, &newattrs, NULL);
+       ret = notify_change(&init_user_ns, dentry, &newattrs, NULL);
        inode_unlock(dentry->d_inode);
        return ret;
 }
@@ -580,7 +580,8 @@ retry_deleg:
                goto out_unlock;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       error = notify_change(path->dentry, &newattrs, &delegated_inode);
+       error = notify_change(&init_user_ns, path->dentry, &newattrs,
+                             &delegated_inode);
 out_unlock:
        inode_unlock(inode);
        if (delegated_inode) {
@@ -671,7 +672,8 @@ retry_deleg:
        inode_lock(inode);
        error = security_path_chown(path, uid, gid);
        if (!error)
-               error = notify_change(path->dentry, &newattrs, &delegated_inode);
+               error = notify_change(&init_user_ns, path->dentry, &newattrs,
+                                     &delegated_inode);
        inode_unlock(inode);
        if (delegated_inode) {
                error = break_deleg_wait(&delegated_inode);
index 4c790cc8042df8590edd4862e6c97d422dd3f48d..8ac9491ceb9a9fa3a90f74d2f93ad427e9ae825a 100644 (file)
@@ -855,7 +855,7 @@ again:
                ORANGEFS_I(inode)->attr_uid = current_fsuid();
                ORANGEFS_I(inode)->attr_gid = current_fsgid();
        }
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        spin_unlock(&inode->i_lock);
        mark_inode_dirty(inode);
 
@@ -876,7 +876,7 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
        int ret;
        gossip_debug(GOSSIP_INODE_DEBUG, "__orangefs_setattr: called on %pd\n",
            dentry);
-       ret = setattr_prepare(dentry, iattr);
+       ret = setattr_prepare(&init_user_ns, dentry, iattr);
        if (ret)
                goto out;
        ret = __orangefs_setattr(d_inode(dentry), iattr);
index e5b616c93e11b673d870a880d5d6233f20da536a..3e9957ae19fa348f9e902cb120d3f7a38619c189 100644 (file)
@@ -235,7 +235,7 @@ static int ovl_set_size(struct dentry *upperdentry, struct kstat *stat)
                .ia_size = stat->size,
        };
 
-       return notify_change(upperdentry, &attr, NULL);
+       return notify_change(&init_user_ns, upperdentry, &attr, NULL);
 }
 
 static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
@@ -247,7 +247,7 @@ static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
                .ia_mtime = stat->mtime,
        };
 
-       return notify_change(upperdentry, &attr, NULL);
+       return notify_change(&init_user_ns, upperdentry, &attr, NULL);
 }
 
 int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
@@ -259,7 +259,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
                        .ia_valid = ATTR_MODE,
                        .ia_mode = stat->mode,
                };
-               err = notify_change(upperdentry, &attr, NULL);
+               err = notify_change(&init_user_ns, upperdentry, &attr, NULL);
        }
        if (!err) {
                struct iattr attr = {
@@ -267,7 +267,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
                        .ia_uid = stat->uid,
                        .ia_gid = stat->gid,
                };
-               err = notify_change(upperdentry, &attr, NULL);
+               err = notify_change(&init_user_ns, upperdentry, &attr, NULL);
        }
        if (!err)
                ovl_set_timestamps(upperdentry, stat);
index 98a23353b19adf0f33ac1ebd0b169f170fa5395c..29840820a46c670dcf4df4ba1825686a7c826abb 100644 (file)
@@ -508,7 +508,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
                        .ia_mode = cattr->mode,
                };
                inode_lock(newdentry->d_inode);
-               err = notify_change(newdentry, &attr, NULL);
+               err = notify_change(&init_user_ns, newdentry, &attr, NULL);
                inode_unlock(newdentry->d_inode);
                if (err)
                        goto out_cleanup;
index c101ebbb7a7792efd9faaa1494c0233f7122e10f..5aa66881dbd7edadd96a215a0786d2a3b885239f 100644 (file)
@@ -21,7 +21,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
        struct dentry *upperdentry;
        const struct cred *old_cred;
 
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
 
@@ -79,7 +79,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
 
                inode_lock(upperdentry->d_inode);
                old_cred = ovl_override_creds(dentry->d_sb);
-               err = notify_change(upperdentry, attr, NULL);
+               err = notify_change(&init_user_ns, upperdentry, attr, NULL);
                revert_creds(old_cred);
                if (!err)
                        ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
index 3e925deaa19a78058e97becd0f198fd33a692556..39b2e9aa0e5ba3e953bcc27bdab39aea306007ca 100644 (file)
@@ -804,7 +804,7 @@ retry:
 
                /* Clear any inherited mode bits */
                inode_lock(work->d_inode);
-               err = notify_change(work, &attr, NULL);
+               err = notify_change(&init_user_ns, work, &attr, NULL);
                inode_unlock(work->d_inode);
                if (err)
                        goto out_dput;
index b4ec9293625e35592431bdc8bb64a26371325881..bb4e63a3684f7fe0c4cbddcc8d6896cd1db332f0 100644 (file)
@@ -693,11 +693,11 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
        if (attr->ia_valid & ATTR_MODE)
                return -EPERM;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index 6c0a05f55d6b12b4551bfd9e5879d01f50209a0e..6d4fabab8aa7db9ba909ff6418d68d00c57ffb8c 100644 (file)
@@ -121,11 +121,11 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
        struct proc_dir_entry *de = PDE(inode);
        int error;
 
-       error = setattr_prepare(dentry, iattr);
+       error = setattr_prepare(&init_user_ns, dentry, iattr);
        if (error)
                return error;
 
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
        mark_inode_dirty(inode);
 
        proc_set_user(de, inode->i_uid, inode->i_gid);
index 317899222d7fdf35b564fc7664311f47194db644..ec67dbc1f7058fac0b47c387d42158d029ed7cb2 100644 (file)
@@ -821,11 +821,11 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
        if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
                return -EPERM;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index 355523f4a4bf3ee2d525fcab44e68809463cc2e8..f0358fe410d3b4ed6fd9f36f786158e0869cc05e 100644 (file)
@@ -165,7 +165,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
        int ret = 0;
 
        /* POSIX UID/GID verification for setting inode attributes */
-       ret = setattr_prepare(dentry, ia);
+       ret = setattr_prepare(&init_user_ns, dentry, ia);
        if (ret)
                return ret;
 
@@ -185,7 +185,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
                }
        }
 
-       setattr_copy(inode, ia);
+       setattr_copy(&init_user_ns, inode, ia);
  out:
        ia->ia_valid = old_ia_valid;
        return ret;
index c76d563dec0e1fae37a4aae748774a1ce33cde9e..944f2b487cf8cac2295b2f86f7556972066224f3 100644 (file)
@@ -3288,7 +3288,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        unsigned int ia_valid;
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -3413,7 +3413,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        if (!error) {
-               setattr_copy(inode, attr);
+               setattr_copy(&init_user_ns, inode, attr);
                mark_inode_dirty(inode);
        }
 
index 45fc79a18594f1a21f9f5234c280187557ae720a..ca7e216b7b9e8e553efbca808349c957f151eab1 100644 (file)
@@ -34,7 +34,7 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
        struct inode *inode = d_inode(dentry);
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -47,7 +47,7 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
                sysv_truncate(inode);
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index 2bc7780d2963c8f709d130a4626326fd03f045d0..76ef392b1e41a619bd39ee2a10b50892b0c03602 100644 (file)
@@ -1265,7 +1265,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
 
        dbg_gen("ino %lu, mode %#x, ia_valid %#x",
                inode->i_ino, inode->i_mode, attr->ia_valid);
-       err = setattr_prepare(dentry, attr);
+       err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
 
index 3671a40ed3c3ef19b82e95c48a31834aa7575b68..7c7d161315c29f39d71a05429c27a9ddb2d31a2c 100644 (file)
@@ -259,7 +259,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
        struct super_block *sb = inode->i_sb;
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -282,7 +282,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
        if (attr->ia_valid & ATTR_MODE)
                udf_update_extra_perms(inode, attr->ia_mode);
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index c843ec858cf7cd0aff4e1dc4b118bbcc9581c7a5..6b51f3b201437a73927bcaf4b8ff28b7714376ba 100644 (file)
@@ -1217,7 +1217,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
        unsigned int ia_valid = attr->ia_valid;
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -1227,7 +1227,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
                        return error;
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        mark_inode_dirty(inode);
        return 0;
 }
index fd3cc42262241f6b39f4f05d8579737403bae27a..4572b91ddb915800fa1548b58777ee95460b8baa 100644 (file)
@@ -62,7 +62,8 @@ int vfs_utimes(const struct path *path, struct timespec64 *times)
        }
 retry_deleg:
        inode_lock(inode);
-       error = notify_change(path->dentry, &newattrs, &delegated_inode);
+       error = notify_change(&init_user_ns, path->dentry, &newattrs,
+                             &delegated_inode);
        inode_unlock(inode);
        if (delegated_inode) {
                error = break_deleg_wait(&delegated_inode);
index 67c8dc9de8aa47129c138147cd3be87c631c856a..08a478d25122bd3d384ad59fac3de355d9a9ae41 100644 (file)
@@ -637,7 +637,7 @@ xfs_vn_change_ok(
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
 
-       return setattr_prepare(dentry, iattr);
+       return setattr_prepare(&init_user_ns, dentry, iattr);
 }
 
 /*
index 569525ee8f69725f25aac3dc009aaca49e6aa073..8a1f696777849c09d0b30f5b93baae8bc96afdc7 100644 (file)
@@ -488,7 +488,7 @@ static int zonefs_inode_setattr(struct dentry *dentry, struct iattr *iattr)
        if (unlikely(IS_IMMUTABLE(inode)))
                return -EPERM;
 
-       ret = setattr_prepare(dentry, iattr);
+       ret = setattr_prepare(&init_user_ns, dentry, iattr);
        if (ret)
                return ret;
 
@@ -516,7 +516,7 @@ static int zonefs_inode_setattr(struct dentry *dentry, struct iattr *iattr)
                        return ret;
        }
 
-       setattr_copy(inode, iattr);
+       setattr_copy(&init_user_ns, inode, iattr);
 
        return 0;
 }
index 2a9d4af6a64d70b568b057fec7cce3c99bce27c8..e3ea1d7c336749adf998b66843e6c0c8e140783c 100644 (file)
@@ -2809,7 +2809,8 @@ static inline int bmap(struct inode *inode,  sector_t *block)
 }
 #endif
 
-extern int notify_change(struct dentry *, struct iattr *, struct inode **);
+int notify_change(struct user_namespace *, struct dentry *,
+                 struct iattr *, struct inode **);
 int inode_permission(struct user_namespace *, struct inode *, int);
 int generic_permission(struct user_namespace *, struct inode *, int);
 static inline int file_permission(struct file *file, int mask)
@@ -3274,9 +3275,10 @@ extern int buffer_migrate_page_norefs(struct address_space *,
 #define buffer_migrate_page_norefs NULL
 #endif
 
-extern int setattr_prepare(struct dentry *, struct iattr *);
+int setattr_prepare(struct user_namespace *, struct dentry *, struct iattr *);
 extern int inode_newsize_ok(const struct inode *, loff_t offset);
-extern void setattr_copy(struct inode *inode, const struct iattr *attr);
+void setattr_copy(struct user_namespace *, struct inode *inode,
+                 const struct iattr *attr);
 
 extern int file_update_time(struct file *file);
 
index 1c68c9edba5e933ed5831d68d2b3077d2b6f4151..1cb451e131ecea25fb6504c18732ab155a21927b 100644 (file)
@@ -1087,7 +1087,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
        struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
        int error;
 
-       error = setattr_prepare(dentry, attr);
+       error = setattr_prepare(&init_user_ns, dentry, attr);
        if (error)
                return error;
 
@@ -1141,7 +1141,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
                }
        }
 
-       setattr_copy(inode, attr);
+       setattr_copy(&init_user_ns, inode, attr);
        if (attr->ia_valid & ATTR_MODE)
                error = posix_acl_chmod(inode, inode->i_mode);
        return error;