fs: port vfs_*() helpers to struct mnt_idmap
authorChristian Brauner <brauner@kernel.org>
Fri, 13 Jan 2023 11:49:10 +0000 (12:49 +0100)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Wed, 18 Jan 2023 16:51:45 +0000 (17:51 +0100)
Convert to struct mnt_idmap.

Last cycle we merged the necessary infrastructure in
256c8aed2b42 ("fs: introduce dedicated idmap type for mounts").
This is just the conversion to struct mnt_idmap.

Currently we still pass around the plain namespace that was attached to a
mount. This is in general pretty convenient but it makes it easy to
conflate namespaces that are relevant on the filesystem with namespaces
that are relevent on the mount level. Especially for non-vfs developers
without detailed knowledge in this area this can be a potential source for
bugs.

Once the conversion to struct mnt_idmap is done all helpers down to the
really low-level helpers will take a struct mnt_idmap argument instead of
two namespace arguments. This way it becomes impossible to conflate the two
eliminating the possibility of any bugs. All of the vfs and all filesystems
only operate on struct mnt_idmap.

Acked-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
25 files changed:
drivers/base/devtmpfs.c
fs/attr.c
fs/cachefiles/interface.c
fs/cachefiles/namei.c
fs/coredump.c
fs/ecryptfs/inode.c
fs/init.c
fs/inode.c
fs/ksmbd/smb2pdu.c
fs/ksmbd/smbacl.c
fs/ksmbd/vfs.c
fs/ksmbd/vfs.h
fs/ksmbd/vfs_cache.c
fs/namei.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/vfs.c
fs/open.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/utimes.c
include/linux/fs.h
ipc/mqueue.c
net/unix/af_unix.c
tools/testing/selftests/bpf/progs/profiler.inc.h

index e4bffeabf344eece30caa8c7fbef990535773303..03e8a95f1f35da21e5c7ad807a712b9342455cb0 100644 (file)
@@ -173,7 +173,7 @@ static int dev_mkdir(const char *name, umode_t mode)
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       err = vfs_mkdir(&init_user_ns, d_inode(path.dentry), dentry, mode);
+       err = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode);
        if (!err)
                /* mark as kernel-created inode */
                d_inode(dentry)->i_private = &thread;
@@ -223,7 +223,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       err = vfs_mknod(&init_user_ns, d_inode(path.dentry), dentry, mode,
+       err = vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode,
                        dev->devt);
        if (!err) {
                struct iattr newattrs;
@@ -233,7 +233,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(&init_user_ns, dentry, &newattrs, NULL);
+               notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
                inode_unlock(d_inode(dentry));
 
                /* mark as kernel-created inode */
@@ -254,7 +254,7 @@ static int dev_rmdir(const char *name)
                return PTR_ERR(dentry);
        if (d_really_is_positive(dentry)) {
                if (d_inode(dentry)->i_private == &thread)
-                       err = vfs_rmdir(&init_user_ns, d_inode(parent.dentry),
+                       err = vfs_rmdir(&nop_mnt_idmap, d_inode(parent.dentry),
                                        dentry);
                else
                        err = -EPERM;
@@ -341,9 +341,9 @@ 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(&init_user_ns, dentry, &newattrs, NULL);
+                       notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
                        inode_unlock(d_inode(dentry));
-                       err = vfs_unlink(&init_user_ns, d_inode(parent.dentry),
+                       err = vfs_unlink(&nop_mnt_idmap, d_inode(parent.dentry),
                                         dentry, NULL);
                        if (!err || err == -ENOENT)
                                deleted = 1;
index b45f30e516fad33ff4f58e3b15f1e754a724cef2..023a3860568a9ce639e333feddc169e8b9b06696 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -352,7 +352,7 @@ EXPORT_SYMBOL(may_setattr);
 
 /**
  * notify_change - modify attributes of a filesytem object
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dentry:    object affected
  * @attr:      new attributes
  * @delegated_inode: returns inode, if the inode is delegated
@@ -371,15 +371,16 @@ EXPORT_SYMBOL(may_setattr);
  * 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
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply pass @nop_mnt_idmap.
  */
-int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
+int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
                  struct iattr *attr, struct inode **delegated_inode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct inode *inode = dentry->d_inode;
        umode_t mode = inode->i_mode;
        int error;
index a69073a1d3f0693b3b90fdc56af1bd85fc4eb14e..40052bdb33655baa88191602dbb03d60d9d8dd1f 100644 (file)
@@ -138,7 +138,7 @@ static int cachefiles_adjust_size(struct cachefiles_object *object)
                newattrs.ia_size = oi_size & PAGE_MASK;
                ret = cachefiles_inject_remove_error();
                if (ret == 0)
-                       ret = notify_change(&init_user_ns, file->f_path.dentry,
+                       ret = notify_change(&nop_mnt_idmap, file->f_path.dentry,
                                            &newattrs, NULL);
                if (ret < 0)
                        goto truncate_failed;
@@ -148,7 +148,7 @@ static int cachefiles_adjust_size(struct cachefiles_object *object)
        newattrs.ia_size = ni_size;
        ret = cachefiles_inject_write_error();
        if (ret == 0)
-               ret = notify_change(&init_user_ns, file->f_path.dentry,
+               ret = notify_change(&nop_mnt_idmap, file->f_path.dentry,
                                    &newattrs, NULL);
 
 truncate_failed:
index 03ca8f2f657ab8d6ade31a45841cdde9cb0d18ed..82219a8f608427489ce6c0de8ed2e7060e4634de 100644 (file)
@@ -130,7 +130,7 @@ retry:
                        goto mkdir_error;
                ret = cachefiles_inject_write_error();
                if (ret == 0)
-                       ret = vfs_mkdir(&init_user_ns, d_inode(dir), subdir, 0700);
+                       ret = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700);
                if (ret < 0) {
                        trace_cachefiles_vfs_error(NULL, d_inode(dir), ret,
                                                   cachefiles_trace_mkdir_error);
@@ -245,7 +245,7 @@ static int cachefiles_unlink(struct cachefiles_cache *cache,
 
        ret = cachefiles_inject_remove_error();
        if (ret == 0) {
-               ret = vfs_unlink(&init_user_ns, d_backing_inode(dir), dentry, NULL);
+               ret = vfs_unlink(&nop_mnt_idmap, d_backing_inode(dir), dentry, NULL);
                if (ret == -EIO)
                        cachefiles_io_error(cache, "Unlink failed");
        }
@@ -382,10 +382,10 @@ try_again:
                cachefiles_io_error(cache, "Rename security error %d", ret);
        } else {
                struct renamedata rd = {
-                       .old_mnt_userns = &init_user_ns,
+                       .old_mnt_idmap  = &nop_mnt_idmap,
                        .old_dir        = d_inode(dir),
                        .old_dentry     = rep,
-                       .new_mnt_userns = &init_user_ns,
+                       .new_mnt_idmap  = &nop_mnt_idmap,
                        .new_dir        = d_inode(cache->graveyard),
                        .new_dentry     = grave,
                };
@@ -451,7 +451,7 @@ struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
 
        ret = cachefiles_inject_write_error();
        if (ret == 0) {
-               file = vfs_tmpfile_open(&init_user_ns, &parentpath, S_IFREG,
+               file = vfs_tmpfile_open(&nop_mnt_idmap, &parentpath, S_IFREG,
                                        O_RDWR | O_LARGEFILE | O_DIRECT,
                                        cache->cache_cred);
                ret = PTR_ERR_OR_ZERO(file);
@@ -714,7 +714,7 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
 
        ret = cachefiles_inject_read_error();
        if (ret == 0)
-               ret = vfs_link(object->file->f_path.dentry, &init_user_ns,
+               ret = vfs_link(object->file->f_path.dentry, &nop_mnt_idmap,
                               d_inode(fan), dentry, NULL);
        if (ret < 0) {
                trace_cachefiles_vfs_error(object, d_inode(fan), ret,
index de78bde2991beb8286bce57899122f559c41ce21..27847d16d2b8941fb44626a9b080bae172e7bc8b 100644 (file)
@@ -644,6 +644,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
                        goto close_fail;
                }
        } else {
+               struct mnt_idmap *idmap;
                struct user_namespace *mnt_userns;
                struct inode *inode;
                int open_flags = O_CREAT | O_RDWR | O_NOFOLLOW |
@@ -722,7 +723,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
                 * a process dumps core while its cwd is e.g. on a vfat
                 * filesystem.
                 */
-               mnt_userns = file_mnt_user_ns(cprm.file);
+               idmap = file_mnt_idmap(cprm.file);
+               mnt_userns = mnt_idmap_owner(idmap);
                if (!vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode),
                                    current_fsuid())) {
                        pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n",
@@ -736,7 +738,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
                }
                if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
                        goto close_fail;
-               if (do_truncate(mnt_userns, cprm.file->f_path.dentry,
+               if (do_truncate(idmap, cprm.file->f_path.dentry,
                                0, 0, cprm.file))
                        goto close_fail;
        }
index f3cd00fac9c3aa3f9a717c2cddaec693293d0642..d2c5a8c55322261858dfe545c7beeafaab7e9f36 100644 (file)
@@ -139,7 +139,7 @@ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
                if (d_unhashed(lower_dentry))
                        rc = -EINVAL;
                else
-                       rc = vfs_unlink(&init_user_ns, lower_dir, lower_dentry,
+                       rc = vfs_unlink(&nop_mnt_idmap, lower_dir, lower_dentry,
                                        NULL);
        }
        if (rc) {
@@ -180,7 +180,7 @@ ecryptfs_do_create(struct inode *directory_inode,
 
        rc = lock_parent(ecryptfs_dentry, &lower_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_create(&init_user_ns, lower_dir,
+               rc = vfs_create(&nop_mnt_idmap, lower_dir,
                                lower_dentry, mode, true);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
@@ -191,7 +191,7 @@ ecryptfs_do_create(struct inode *directory_inode,
        inode = __ecryptfs_get_inode(d_inode(lower_dentry),
                                     directory_inode->i_sb);
        if (IS_ERR(inode)) {
-               vfs_unlink(&init_user_ns, lower_dir, lower_dentry, NULL);
+               vfs_unlink(&nop_mnt_idmap, lower_dir, lower_dentry, NULL);
                goto out_lock;
        }
        fsstack_copy_attr_times(directory_inode, lower_dir);
@@ -434,7 +434,7 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
        lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
        rc = lock_parent(new_dentry, &lower_new_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_link(lower_old_dentry, &init_user_ns, lower_dir,
+               rc = vfs_link(lower_old_dentry, &nop_mnt_idmap, lower_dir,
                              lower_new_dentry, NULL);
        if (rc || d_really_is_negative(lower_new_dentry))
                goto out_lock;
@@ -478,7 +478,7 @@ static int ecryptfs_symlink(struct user_namespace *mnt_userns,
                                                  strlen(symname));
        if (rc)
                goto out_lock;
-       rc = vfs_symlink(&init_user_ns, lower_dir, lower_dentry,
+       rc = vfs_symlink(&nop_mnt_idmap, lower_dir, lower_dentry,
                         encoded_symname);
        kfree(encoded_symname);
        if (rc || d_really_is_negative(lower_dentry))
@@ -504,7 +504,7 @@ static int ecryptfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 
        rc = lock_parent(dentry, &lower_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_mkdir(&init_user_ns, lower_dir,
+               rc = vfs_mkdir(&nop_mnt_idmap, lower_dir,
                               lower_dentry, mode);
        if (rc || d_really_is_negative(lower_dentry))
                goto out;
@@ -533,7 +533,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
                if (d_unhashed(lower_dentry))
                        rc = -EINVAL;
                else
-                       rc = vfs_rmdir(&init_user_ns, lower_dir, lower_dentry);
+                       rc = vfs_rmdir(&nop_mnt_idmap, lower_dir, lower_dentry);
        }
        if (!rc) {
                clear_nlink(d_inode(dentry));
@@ -557,7 +557,7 @@ ecryptfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
 
        rc = lock_parent(dentry, &lower_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_mknod(&init_user_ns, lower_dir,
+               rc = vfs_mknod(&nop_mnt_idmap, lower_dir,
                               lower_dentry, mode, dev);
        if (rc || d_really_is_negative(lower_dentry))
                goto out;
@@ -616,10 +616,10 @@ ecryptfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
                goto out_lock;
        }
 
-       rd.old_mnt_userns       = &init_user_ns;
+       rd.old_mnt_idmap        = &nop_mnt_idmap;
        rd.old_dir              = d_inode(lower_old_dir_dentry);
        rd.old_dentry           = lower_old_dentry;
-       rd.new_mnt_userns       = &init_user_ns;
+       rd.new_mnt_idmap        = &nop_mnt_idmap;
        rd.new_dir              = d_inode(lower_new_dir_dentry);
        rd.new_dentry           = lower_new_dentry;
        rc = vfs_rename(&rd);
@@ -856,7 +856,7 @@ 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(&init_user_ns, lower_dentry,
+               rc = notify_change(&nop_mnt_idmap, lower_dentry,
                                   &lower_ia, NULL);
                inode_unlock(d_inode(lower_dentry));
        }
@@ -965,7 +965,7 @@ static int ecryptfs_setattr(struct user_namespace *mnt_userns,
                lower_ia.ia_valid &= ~ATTR_MODE;
 
        inode_lock(d_inode(lower_dentry));
-       rc = notify_change(&init_user_ns, lower_dentry, &lower_ia, NULL);
+       rc = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL);
        inode_unlock(d_inode(lower_dentry));
 out:
        fsstack_copy_attr_all(inode, lower_inode);
index 5c36adaa9b448d6afcb7fb49a704cf131081f99b..f43f1e78bf7aef768d6a5a0fe9eea4b94e9fd211 100644 (file)
--- a/fs/init.c
+++ b/fs/init.c
@@ -157,7 +157,7 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
                mode &= ~current_umask();
        error = security_path_mknod(&path, dentry, mode, dev);
        if (!error)
-               error = vfs_mknod(mnt_user_ns(path.mnt), path.dentry->d_inode,
+               error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
                                  dentry, mode, new_decode_dev(dev));
        done_path_create(&path, dentry);
        return error;
@@ -167,6 +167,7 @@ int __init init_link(const char *oldname, const char *newname)
 {
        struct dentry *new_dentry;
        struct path old_path, new_path;
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        int error;
 
@@ -182,14 +183,15 @@ int __init init_link(const char *oldname, const char *newname)
        error = -EXDEV;
        if (old_path.mnt != new_path.mnt)
                goto out_dput;
-       mnt_userns = mnt_user_ns(new_path.mnt);
+       idmap = mnt_idmap(new_path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        error = may_linkat(mnt_userns, &old_path);
        if (unlikely(error))
                goto out_dput;
        error = security_path_link(old_path.dentry, &new_path, new_dentry);
        if (error)
                goto out_dput;
-       error = vfs_link(old_path.dentry, mnt_userns, new_path.dentry->d_inode,
+       error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
                         new_dentry, NULL);
 out_dput:
        done_path_create(&new_path, new_dentry);
@@ -209,7 +211,7 @@ int __init init_symlink(const char *oldname, const char *newname)
                return PTR_ERR(dentry);
        error = security_path_symlink(&path, dentry, oldname);
        if (!error)
-               error = vfs_symlink(mnt_user_ns(path.mnt), path.dentry->d_inode,
+               error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
                                    dentry, oldname);
        done_path_create(&path, dentry);
        return error;
@@ -233,7 +235,7 @@ int __init init_mkdir(const char *pathname, umode_t mode)
                mode &= ~current_umask();
        error = security_path_mkdir(&path, dentry, mode);
        if (!error)
-               error = vfs_mkdir(mnt_user_ns(path.mnt), path.dentry->d_inode,
+               error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
                                  dentry, mode);
        done_path_create(&path, dentry);
        return error;
index f453eb58fd03de04b32837af37d4f0701e8ae16f..84b5da325ee856d4564dfabd1c088b8e2798f08a 100644 (file)
@@ -1972,7 +1972,7 @@ int dentry_needs_remove_privs(struct user_namespace *mnt_userns,
        return mask;
 }
 
-static int __remove_privs(struct user_namespace *mnt_userns,
+static int __remove_privs(struct mnt_idmap *idmap,
                          struct dentry *dentry, int kill)
 {
        struct iattr newattrs;
@@ -1982,7 +1982,7 @@ static int __remove_privs(struct user_namespace *mnt_userns,
         * Note we call this on write, so notify_change will not
         * encounter any conflicting delegations:
         */
-       return notify_change(mnt_userns, dentry, &newattrs, NULL);
+       return notify_change(idmap, dentry, &newattrs, NULL);
 }
 
 static int __file_remove_privs(struct file *file, unsigned int flags)
@@ -2003,7 +2003,7 @@ static int __file_remove_privs(struct file *file, unsigned int flags)
                if (flags & IOCB_NOWAIT)
                        return -EAGAIN;
 
-               error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
+               error = __remove_privs(file_mnt_idmap(file), dentry, kill);
        }
 
        if (!error)
index 14d7f3599c6397a1dba915509b03a1644cc7ed2a..f787f66b329c189ccb37323679f41e036f5ebbe1 100644 (file)
@@ -5615,6 +5615,7 @@ static int set_file_basic_info(struct ksmbd_file *fp,
        struct iattr attrs;
        struct file *filp;
        struct inode *inode;
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        int rc = 0;
 
@@ -5624,7 +5625,8 @@ static int set_file_basic_info(struct ksmbd_file *fp,
        attrs.ia_valid = 0;
        filp = fp->filp;
        inode = file_inode(filp);
-       user_ns = file_mnt_user_ns(filp);
+       idmap = file_mnt_idmap(filp);
+       user_ns = mnt_idmap_owner(idmap);
 
        if (file_info->CreationTime)
                fp->create_time = le64_to_cpu(file_info->CreationTime);
@@ -5686,7 +5688,7 @@ static int set_file_basic_info(struct ksmbd_file *fp,
                inode_lock(inode);
                inode->i_ctime = attrs.ia_ctime;
                attrs.ia_valid &= ~ATTR_CTIME;
-               rc = notify_change(user_ns, dentry, &attrs, NULL);
+               rc = notify_change(idmap, dentry, &attrs, NULL);
                inode_unlock(inode);
        }
        return rc;
index ab5c68cc0e13bb252adf9fb6dfc73728df443f9a..6490342bbb386e2c62be879a26e77290e9bd760b 100644 (file)
@@ -1360,7 +1360,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
        int rc;
        struct smb_fattr fattr = {{0}};
        struct inode *inode = d_inode(path->dentry);
-       struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+       struct mnt_idmap *idmap = mnt_idmap(path->mnt);
+       struct user_namespace *user_ns = mnt_idmap_owner(idmap);
        struct iattr newattrs;
 
        fattr.cf_uid = INVALID_UID;
@@ -1403,7 +1404,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
        }
 
        inode_lock(inode);
-       rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
+       rc = notify_change(idmap, path->dentry, &newattrs, NULL);
        inode_unlock(inode);
        if (rc)
                goto out;
index ff0e7a4fcd4de5df2892ca6de1f43319477be2cb..5b284dd61056b361de033087c4328ee4abdc26e5 100644 (file)
@@ -177,7 +177,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
        }
 
        mode |= S_IFREG;
-       err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
+       err = vfs_create(mnt_idmap(path.mnt), d_inode(path.dentry),
                         dentry, mode, true);
        if (!err) {
                ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
@@ -199,6 +199,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
  */
 int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        struct path path;
        struct dentry *dentry;
@@ -215,9 +216,10 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
                return err;
        }
 
-       user_ns = mnt_user_ns(path.mnt);
+       idmap = mnt_idmap(path.mnt);
+       user_ns = mnt_idmap_owner(idmap);
        mode |= S_IFDIR;
-       err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
+       err = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode);
        if (err) {
                goto out;
        } else if (d_unhashed(dentry)) {
@@ -583,6 +585,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
  */
 int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        struct path path;
        struct dentry *parent;
@@ -598,7 +601,8 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
                return err;
        }
 
-       user_ns = mnt_user_ns(path.mnt);
+       idmap = mnt_idmap(path.mnt);
+       user_ns = mnt_idmap_owner(idmap);
        parent = dget_parent(path.dentry);
        err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
        if (err) {
@@ -614,12 +618,12 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
        }
 
        if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
-               err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
+               err = vfs_rmdir(idmap, d_inode(parent), path.dentry);
                if (err && err != -ENOTEMPTY)
                        ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
                                    err);
        } else {
-               err = vfs_unlink(user_ns, d_inode(parent), path.dentry, NULL);
+               err = vfs_unlink(idmap, d_inode(parent), path.dentry, NULL);
                if (err)
                        ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
                                    err);
@@ -672,7 +676,7 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
                goto out3;
        }
 
-       err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
+       err = vfs_link(oldpath.dentry, mnt_idmap(newpath.mnt),
                       d_inode(newpath.dentry),
                       dentry, NULL);
        if (err)
@@ -711,10 +715,10 @@ static int ksmbd_validate_entry_in_use(struct dentry *src_dent)
 }
 
 static int __ksmbd_vfs_rename(struct ksmbd_work *work,
-                             struct user_namespace *src_user_ns,
+                             struct mnt_idmap *src_idmap,
                              struct dentry *src_dent_parent,
                              struct dentry *src_dent,
-                             struct user_namespace *dst_user_ns,
+                             struct mnt_idmap *dst_idmap,
                              struct dentry *dst_dent_parent,
                              struct dentry *trap_dent,
                              char *dst_name)
@@ -740,8 +744,8 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
        if (ksmbd_override_fsids(work))
                return -ENOMEM;
 
-       dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
-                             strlen(dst_name));
+       dst_dent = lookup_one(mnt_idmap_owner(dst_idmap), dst_name,
+                             dst_dent_parent, strlen(dst_name));
        err = PTR_ERR(dst_dent);
        if (IS_ERR(dst_dent)) {
                pr_err("lookup failed %s [%d]\n", dst_name, err);
@@ -751,10 +755,10 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
        err = -ENOTEMPTY;
        if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
                struct renamedata rd = {
-                       .old_mnt_userns = src_user_ns,
+                       .old_mnt_idmap  = src_idmap,
                        .old_dir        = d_inode(src_dent_parent),
                        .old_dentry     = src_dent,
-                       .new_mnt_userns = dst_user_ns,
+                       .new_mnt_idmap  = dst_idmap,
                        .new_dir        = d_inode(dst_dent_parent),
                        .new_dentry     = dst_dent,
                };
@@ -772,6 +776,7 @@ out:
 int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
                        char *newname)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        struct path dst_path;
        struct dentry *src_dent_parent, *dst_dent_parent;
@@ -800,7 +805,8 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
        trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
        dget(src_dent);
        dget(dst_dent_parent);
-       user_ns = file_mnt_user_ns(fp->filp);
+       idmap = file_mnt_idmap(fp->filp);
+       user_ns = mnt_idmap_owner(idmap);
        src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
                               src_dent->d_name.len);
        if (IS_ERR(src_child)) {
@@ -816,10 +822,10 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
        dput(src_child);
 
        err = __ksmbd_vfs_rename(work,
-                                user_ns,
+                                idmap,
                                 src_dent_parent,
                                 src_dent,
-                                mnt_user_ns(dst_path.mnt),
+                                mnt_idmap(dst_path.mnt),
                                 dst_dent_parent,
                                 trap_dent,
                                 dst_name);
@@ -1080,20 +1086,21 @@ int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
        return vfs_removexattr(user_ns, dentry, attr_name);
 }
 
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
+int ksmbd_vfs_unlink(struct mnt_idmap *idmap,
                     struct dentry *dir, struct dentry *dentry)
 {
        int err = 0;
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
 
-       err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
+       err = ksmbd_vfs_lock_parent(mnt_userns, dir, dentry);
        if (err)
                return err;
        dget(dentry);
 
        if (S_ISDIR(d_inode(dentry)->i_mode))
-               err = vfs_rmdir(user_ns, d_inode(dir), dentry);
+               err = vfs_rmdir(idmap, d_inode(dir), dentry);
        else
-               err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL);
+               err = vfs_unlink(idmap, d_inode(dir), dentry, NULL);
 
        dput(dentry);
        inode_unlock(d_inode(dir));
index 0d73d735cc3991b137564e79af1b3de57c7b9c82..0c9b04ae5fbf665068d485a1f99843aab203db83 100644 (file)
@@ -131,8 +131,8 @@ struct file_allocated_range_buffer;
 int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
                         struct file_allocated_range_buffer *ranges,
                         unsigned int in_count, unsigned int *out_count);
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
-                    struct dentry *dir, struct dentry *dentry);
+int ksmbd_vfs_unlink(struct mnt_idmap *idmap, struct dentry *dir,
+                    struct dentry *dentry);
 void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
 int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
                                struct user_namespace *user_ns,
index da9163b003503acb8085ff2fe5e7189a76658c45..8489ff4d601aab66be46e5f5a66db2063c227951 100644 (file)
@@ -266,7 +266,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
                        dir = dentry->d_parent;
                        ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
                        write_unlock(&ci->m_lock);
-                       ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
+                       ksmbd_vfs_unlink(file_mnt_idmap(filp), dir, dentry);
                        write_lock(&ci->m_lock);
                }
                write_unlock(&ci->m_lock);
index 309ae6fc8c993b8057a560da88de4971fa004127..3e727efed860ef76f554a064732657f612dffdce 100644 (file)
@@ -3084,7 +3084,7 @@ static inline umode_t vfs_prepare_mode(struct user_namespace *mnt_userns,
 
 /**
  * vfs_create - create new file
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new file
@@ -3092,16 +3092,19 @@ static inline umode_t vfs_prepare_mode(struct user_namespace *mnt_userns,
  *
  * Create a new file.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_create(struct mnt_idmap *idmap, struct inode *dir,
               struct dentry *dentry, umode_t mode, bool want_excl)
 {
-       int error = may_create(mnt_userns, dir, dentry);
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
+       int error;
+
+       error = may_create(mnt_userns, dir, dentry);
        if (error)
                return error;
 
@@ -3203,7 +3206,7 @@ static int may_open(struct user_namespace *mnt_userns, const struct path *path,
        return 0;
 }
 
-static int handle_truncate(struct user_namespace *mnt_userns, struct file *filp)
+static int handle_truncate(struct mnt_idmap *idmap, struct file *filp)
 {
        const struct path *path = &filp->f_path;
        struct inode *inode = path->dentry->d_inode;
@@ -3213,7 +3216,7 @@ static int handle_truncate(struct user_namespace *mnt_userns, struct file *filp)
 
        error = security_file_truncate(filp);
        if (!error) {
-               error = do_truncate(mnt_userns, path->dentry, 0,
+               error = do_truncate(idmap, path->dentry, 0,
                                    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
                                    filp);
        }
@@ -3513,6 +3516,7 @@ finish_lookup:
 static int do_open(struct nameidata *nd,
                   struct file *file, const struct open_flags *op)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        int open_flag = op->open_flag;
        bool do_truncate;
@@ -3526,7 +3530,8 @@ static int do_open(struct nameidata *nd,
        }
        if (!(file->f_mode & FMODE_CREATED))
                audit_inode(nd->name, nd->path.dentry, 0);
-       mnt_userns = mnt_user_ns(nd->path.mnt);
+       idmap = mnt_idmap(nd->path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        if (open_flag & O_CREAT) {
                if ((open_flag & O_EXCL) && !(file->f_mode & FMODE_CREATED))
                        return -EEXIST;
@@ -3558,7 +3563,7 @@ static int do_open(struct nameidata *nd,
        if (!error)
                error = ima_file_check(file, op->acc_mode);
        if (!error && do_truncate)
-               error = handle_truncate(mnt_userns, file);
+               error = handle_truncate(idmap, file);
        if (unlikely(error > 0)) {
                WARN_ON(1);
                error = -EINVAL;
@@ -3570,23 +3575,24 @@ static int do_open(struct nameidata *nd,
 
 /**
  * vfs_tmpfile - create tmpfile
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new tmpfile
  * @open_flag: flags
  *
  * Create a temporary file.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-static int vfs_tmpfile(struct user_namespace *mnt_userns,
+static int vfs_tmpfile(struct mnt_idmap *idmap,
                       const struct path *parentpath,
                       struct file *file, umode_t mode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct dentry *child;
        struct inode *dir = d_inode(parentpath->dentry);
        struct inode *inode;
@@ -3625,7 +3631,7 @@ static int vfs_tmpfile(struct user_namespace *mnt_userns,
 
 /**
  * vfs_tmpfile_open - open a tmpfile for kernel internal use
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @parentpath:        path of the base directory
  * @mode:      mode of the new tmpfile
  * @open_flag: flags
@@ -3635,7 +3641,7 @@ static int vfs_tmpfile(struct user_namespace *mnt_userns,
  * hence this is only for kernel internal use, and must not be installed into
  * file tables or such.
  */
-struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
+struct file *vfs_tmpfile_open(struct mnt_idmap *idmap,
                          const struct path *parentpath,
                          umode_t mode, int open_flag, const struct cred *cred)
 {
@@ -3644,7 +3650,7 @@ struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
 
        file = alloc_empty_file_noaccount(open_flag, cred);
        if (!IS_ERR(file)) {
-               error = vfs_tmpfile(mnt_userns, parentpath, file, mode);
+               error = vfs_tmpfile(idmap, parentpath, file, mode);
                if (error) {
                        fput(file);
                        file = ERR_PTR(error);
@@ -3658,7 +3664,6 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
                const struct open_flags *op,
                struct file *file)
 {
-       struct user_namespace *mnt_userns;
        struct path path;
        int error = path_lookupat(nd, flags | LOOKUP_DIRECTORY, &path);
 
@@ -3667,8 +3672,7 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
        error = mnt_want_write(path.mnt);
        if (unlikely(error))
                goto out;
-       mnt_userns = mnt_user_ns(path.mnt);
-       error = vfs_tmpfile(mnt_userns, &path, file, op->mode);
+       error = vfs_tmpfile(mnt_idmap(path.mnt), &path, file, op->mode);
        if (error)
                goto out2;
        audit_inode(nd->name, file->f_path.dentry, 0);
@@ -3873,7 +3877,7 @@ EXPORT_SYMBOL(user_path_create);
 
 /**
  * vfs_mknod - create device node or file
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new device node or file
@@ -3881,15 +3885,16 @@ EXPORT_SYMBOL(user_path_create);
  *
  * Create a device node or file.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
              struct dentry *dentry, umode_t mode, dev_t dev)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
        int error = may_create(mnt_userns, dir, dentry);
 
@@ -3939,6 +3944,7 @@ static int may_mknod(umode_t mode)
 static int do_mknodat(int dfd, struct filename *name, umode_t mode,
                unsigned int dev)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        struct dentry *dentry;
        struct path path;
@@ -3959,20 +3965,21 @@ retry:
        if (error)
                goto out2;
 
-       mnt_userns = mnt_user_ns(path.mnt);
+       idmap = mnt_idmap(path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        switch (mode & S_IFMT) {
                case 0: case S_IFREG:
-                       error = vfs_create(mnt_userns, path.dentry->d_inode,
+                       error = vfs_create(idmap, path.dentry->d_inode,
                                           dentry, mode, true);
                        if (!error)
                                ima_post_path_mknod(mnt_userns, dentry);
                        break;
                case S_IFCHR: case S_IFBLK:
-                       error = vfs_mknod(mnt_userns, path.dentry->d_inode,
+                       error = vfs_mknod(idmap, path.dentry->d_inode,
                                          dentry, mode, new_decode_dev(dev));
                        break;
                case S_IFIFO: case S_IFSOCK:
-                       error = vfs_mknod(mnt_userns, path.dentry->d_inode,
+                       error = vfs_mknod(idmap, path.dentry->d_inode,
                                          dentry, mode, 0);
                        break;
        }
@@ -4000,25 +4007,27 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
 
 /**
  * vfs_mkdir - create directory
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new directory
  *
  * Create a directory.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
              struct dentry *dentry, umode_t mode)
 {
-       int error = may_create(mnt_userns, dir, dentry);
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
+       int error;
        unsigned max_links = dir->i_sb->s_max_links;
 
+       error = may_create(mnt_userns, dir, dentry);
        if (error)
                return error;
 
@@ -4056,10 +4065,8 @@ retry:
        error = security_path_mkdir(&path, dentry,
                        mode_strip_umask(path.dentry->d_inode, mode));
        if (!error) {
-               struct user_namespace *mnt_userns;
-               mnt_userns = mnt_user_ns(path.mnt);
-               error = vfs_mkdir(mnt_userns, path.dentry->d_inode, dentry,
-                                 mode);
+               error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
+                                 dentry, mode);
        }
        done_path_create(&path, dentry);
        if (retry_estale(error, lookup_flags)) {
@@ -4083,21 +4090,22 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
 
 /**
  * vfs_rmdir - remove directory
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  *
  * Remove a directory.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_rmdir(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
                     struct dentry *dentry)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int error = may_delete(mnt_userns, dir, dentry, 1);
 
        if (error)
@@ -4138,7 +4146,6 @@ EXPORT_SYMBOL(vfs_rmdir);
 
 int do_rmdir(int dfd, struct filename *name)
 {
-       struct user_namespace *mnt_userns;
        int error;
        struct dentry *dentry;
        struct path path;
@@ -4178,8 +4185,7 @@ retry:
        error = security_path_rmdir(&path, dentry);
        if (error)
                goto exit4;
-       mnt_userns = mnt_user_ns(path.mnt);
-       error = vfs_rmdir(mnt_userns, path.dentry->d_inode, dentry);
+       error = vfs_rmdir(mnt_idmap(path.mnt), path.dentry->d_inode, dentry);
 exit4:
        dput(dentry);
 exit3:
@@ -4203,7 +4209,7 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
 
 /**
  * vfs_unlink - unlink a filesystem object
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       parent directory
  * @dentry:    victim
  * @delegated_inode: returns victim inode, if the inode is delegated.
@@ -4220,15 +4226,16 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
               struct dentry *dentry, struct inode **delegated_inode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct inode *target = dentry->d_inode;
        int error = may_delete(mnt_userns, dir, dentry, 0);
 
@@ -4304,7 +4311,6 @@ retry_deleg:
        dentry = __lookup_hash(&last, path.dentry, lookup_flags);
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
-               struct user_namespace *mnt_userns;
 
                /* Why not before? Because we want correct error value */
                if (last.name[last.len])
@@ -4316,9 +4322,8 @@ retry_deleg:
                error = security_path_unlink(&path, dentry);
                if (error)
                        goto exit3;
-               mnt_userns = mnt_user_ns(path.mnt);
-               error = vfs_unlink(mnt_userns, path.dentry->d_inode, dentry,
-                                  &delegated_inode);
+               error = vfs_unlink(mnt_idmap(path.mnt), path.dentry->d_inode,
+                                  dentry, &delegated_inode);
 exit3:
                dput(dentry);
        }
@@ -4370,22 +4375,23 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname)
 
 /**
  * vfs_symlink - create symlink
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @oldname:   name of the file to link to
  *
  * Create a symlink.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
                struct dentry *dentry, const char *oldname)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int error = may_create(mnt_userns, dir, dentry);
 
        if (error)
@@ -4423,13 +4429,9 @@ retry:
                goto out_putnames;
 
        error = security_path_symlink(&path, dentry, from->name);
-       if (!error) {
-               struct user_namespace *mnt_userns;
-
-               mnt_userns = mnt_user_ns(path.mnt);
-               error = vfs_symlink(mnt_userns, path.dentry->d_inode, dentry,
-                                   from->name);
-       }
+       if (!error)
+               error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
+                                   dentry, from->name);
        done_path_create(&path, dentry);
        if (retry_estale(error, lookup_flags)) {
                lookup_flags |= LOOKUP_REVAL;
@@ -4455,7 +4457,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn
 /**
  * vfs_link - create a new link
  * @old_dentry:        object to be linked
- * @mnt_userns:        the user namespace of the mount
+ * @idmap:     idmap of the mount
  * @dir:       new parent
  * @new_dentry:        where to create the new link
  * @delegated_inode: returns inode needing a delegation break
@@ -4472,16 +4474,17 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.
  *
- * 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.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_link(struct dentry *old_dentry, struct user_namespace *mnt_userns,
+int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap,
             struct inode *dir, struct dentry *new_dentry,
             struct inode **delegated_inode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct inode *inode = old_dentry->d_inode;
        unsigned max_links = dir->i_sb->s_max_links;
        int error;
@@ -4553,6 +4556,7 @@ EXPORT_SYMBOL(vfs_link);
 int do_linkat(int olddfd, struct filename *old, int newdfd,
              struct filename *new, int flags)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        struct dentry *new_dentry;
        struct path old_path, new_path;
@@ -4590,14 +4594,15 @@ retry:
        error = -EXDEV;
        if (old_path.mnt != new_path.mnt)
                goto out_dput;
-       mnt_userns = mnt_user_ns(new_path.mnt);
+       idmap = mnt_idmap(new_path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        error = may_linkat(mnt_userns, &old_path);
        if (unlikely(error))
                goto out_dput;
        error = security_path_link(old_path.dentry, &new_path, new_dentry);
        if (error)
                goto out_dput;
-       error = vfs_link(old_path.dentry, mnt_userns, new_path.dentry->d_inode,
+       error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
                         new_dentry, &delegated_inode);
 out_dput:
        done_path_create(&new_path, new_dentry);
@@ -4693,24 +4698,26 @@ int vfs_rename(struct renamedata *rd)
        bool new_is_dir = false;
        unsigned max_links = new_dir->i_sb->s_max_links;
        struct name_snapshot old_name;
+       struct user_namespace *old_mnt_userns = mnt_idmap_owner(rd->old_mnt_idmap),
+                             *new_mnt_userns = mnt_idmap_owner(rd->new_mnt_idmap);
 
        if (source == target)
                return 0;
 
-       error = may_delete(rd->old_mnt_userns, old_dir, old_dentry, is_dir);
+       error = may_delete(old_mnt_userns, old_dir, old_dentry, is_dir);
        if (error)
                return error;
 
        if (!target) {
-               error = may_create(rd->new_mnt_userns, new_dir, new_dentry);
+               error = may_create(new_mnt_userns, new_dir, new_dentry);
        } else {
                new_is_dir = d_is_dir(new_dentry);
 
                if (!(flags & RENAME_EXCHANGE))
-                       error = may_delete(rd->new_mnt_userns, new_dir,
+                       error = may_delete(new_mnt_userns, new_dir,
                                           new_dentry, is_dir);
                else
-                       error = may_delete(rd->new_mnt_userns, new_dir,
+                       error = may_delete(new_mnt_userns, new_dir,
                                           new_dentry, new_is_dir);
        }
        if (error)
@@ -4725,13 +4732,13 @@ int vfs_rename(struct renamedata *rd)
         */
        if (new_dir != old_dir) {
                if (is_dir) {
-                       error = inode_permission(rd->old_mnt_userns, source,
+                       error = inode_permission(old_mnt_userns, source,
                                                 MAY_WRITE);
                        if (error)
                                return error;
                }
                if ((flags & RENAME_EXCHANGE) && new_is_dir) {
-                       error = inode_permission(rd->new_mnt_userns, target,
+                       error = inode_permission(new_mnt_userns, target,
                                                 MAY_WRITE);
                        if (error)
                                return error;
@@ -4776,7 +4783,7 @@ int vfs_rename(struct renamedata *rd)
                if (error)
                        goto out;
        }
-       error = old_dir->i_op->rename(rd->new_mnt_userns, old_dir, old_dentry,
+       error = old_dir->i_op->rename(new_mnt_userns, old_dir, old_dentry,
                                      new_dir, new_dentry, flags);
        if (error)
                goto out;
@@ -4921,10 +4928,10 @@ retry_deleg:
 
        rd.old_dir         = old_path.dentry->d_inode;
        rd.old_dentry      = old_dentry;
-       rd.old_mnt_userns  = mnt_user_ns(old_path.mnt);
+       rd.old_mnt_idmap   = mnt_idmap(old_path.mnt);
        rd.new_dir         = new_path.dentry->d_inode;
        rd.new_dentry      = new_dentry;
-       rd.new_mnt_userns  = mnt_user_ns(new_path.mnt);
+       rd.new_mnt_idmap   = mnt_idmap(new_path.mnt);
        rd.delegated_inode = &delegated_inode;
        rd.flags           = flags;
        error = vfs_rename(&rd);
index d01b29aba66237ca43755d0f739cbe38585cac89..f41992ecd0d791b1bb03ad667fb4d70f5e4b2912 100644 (file)
@@ -320,7 +320,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
                iap->ia_mode &= ~current_umask();
 
        fh_fill_pre_attrs(fhp);
-       host_err = vfs_create(&init_user_ns, inode, child, iap->ia_mode, true);
+       host_err = vfs_create(&nop_mnt_idmap, inode, child, iap->ia_mode, true);
        if (host_err < 0) {
                status = nfserrno(host_err);
                goto out;
index 78b8cd9651d5b929cd1352f55ee652c577f61960..3509e73abe1f4b28cda80dab23b8372c11f0b55b 100644 (file)
@@ -233,7 +233,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
                 * as well be forgiving and just succeed silently.
                 */
                goto out_put;
-       status = vfs_mkdir(&init_user_ns, d_inode(dir), dentry, S_IRWXU);
+       status = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU);
 out_put:
        dput(dentry);
 out_unlock:
@@ -353,7 +353,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
        status = -ENOENT;
        if (d_really_is_negative(dentry))
                goto out;
-       status = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
+       status = vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry);
 out:
        dput(dentry);
 out_unlock:
@@ -443,7 +443,7 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
        if (nfs4_has_reclaimed_state(name, nn))
                goto out_free;
 
-       status = vfs_rmdir(&init_user_ns, d_inode(parent), child);
+       status = vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child);
        if (status)
                printk("failed to remove client recovery directory %pd\n",
                                child);
index 4c3a0d84043c9b2c4fc2088640ba6c9a6e8f5920..371d7f03fe2dac6d0fef5d90b61f78c67e6f5850 100644 (file)
@@ -426,7 +426,7 @@ static int __nfsd_setattr(struct dentry *dentry, struct iattr *iap)
                if (iap->ia_size < 0)
                        return -EFBIG;
 
-               host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL);
+               host_err = notify_change(&nop_mnt_idmap, dentry, &size_attr, NULL);
                if (host_err)
                        return host_err;
                iap->ia_valid &= ~ATTR_SIZE;
@@ -444,7 +444,7 @@ static int __nfsd_setattr(struct dentry *dentry, struct iattr *iap)
                return 0;
 
        iap->ia_valid |= ATTR_CTIME;
-       return notify_change(&init_user_ns, dentry, iap, NULL);
+       return notify_change(&nop_mnt_idmap, dentry, iap, NULL);
 }
 
 /**
@@ -1363,12 +1363,13 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
        err = 0;
        switch (type) {
        case S_IFREG:
-               host_err = vfs_create(&init_user_ns, dirp, dchild, iap->ia_mode, true);
+               host_err = vfs_create(&nop_mnt_idmap, dirp, dchild,
+                                     iap->ia_mode, true);
                if (!host_err)
                        nfsd_check_ignore_resizing(iap);
                break;
        case S_IFDIR:
-               host_err = vfs_mkdir(&init_user_ns, dirp, dchild, iap->ia_mode);
+               host_err = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode);
                if (!host_err && unlikely(d_unhashed(dchild))) {
                        struct dentry *d;
                        d = lookup_one_len(dchild->d_name.name,
@@ -1396,7 +1397,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
        case S_IFBLK:
        case S_IFIFO:
        case S_IFSOCK:
-               host_err = vfs_mknod(&init_user_ns, dirp, dchild,
+               host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild,
                                     iap->ia_mode, rdev);
                break;
        default:
@@ -1557,7 +1558,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out_drop_write;
        }
        fh_fill_pre_attrs(fhp);
-       host_err = vfs_symlink(&init_user_ns, d_inode(dentry), dnew, path);
+       host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path);
        err = nfserrno(host_err);
        cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
        if (!err)
@@ -1625,7 +1626,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
        if (d_really_is_negative(dold))
                goto out_dput;
        fh_fill_pre_attrs(ffhp);
-       host_err = vfs_link(dold, &init_user_ns, dirp, dnew, NULL);
+       host_err = vfs_link(dold, &nop_mnt_idmap, dirp, dnew, NULL);
        fh_fill_post_attrs(ffhp);
        inode_unlock(dirp);
        if (!host_err) {
@@ -1745,10 +1746,10 @@ retry:
                goto out_dput_old;
        } else {
                struct renamedata rd = {
-                       .old_mnt_userns = &init_user_ns,
+                       .old_mnt_idmap  = &nop_mnt_idmap,
                        .old_dir        = fdir,
                        .old_dentry     = odentry,
-                       .new_mnt_userns = &init_user_ns,
+                       .new_mnt_idmap  = &nop_mnt_idmap,
                        .new_dir        = tdir,
                        .new_dentry     = ndentry,
                };
@@ -1850,14 +1851,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                        nfsd_close_cached_files(rdentry);
 
                for (retries = 1;;) {
-                       host_err = vfs_unlink(&init_user_ns, dirp, rdentry, NULL);
+                       host_err = vfs_unlink(&nop_mnt_idmap, dirp, rdentry, NULL);
                        if (host_err != -EAGAIN || !retries--)
                                break;
                        if (!nfsd_wait_for_delegreturn(rqstp, rinode))
                                break;
                }
        } else {
-               host_err = vfs_rmdir(&init_user_ns, dirp, rdentry);
+               host_err = vfs_rmdir(&nop_mnt_idmap, dirp, rdentry);
        }
        fh_fill_post_attrs(fhp);
 
index 82c1a28b330897661229b6539a2befc031a6d0ce..60a81db586ef53e1e936ac4bd06a30b506b88e5c 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 
 #include "internal.h"
 
-int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
+int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry,
                loff_t length, unsigned int time_attrs, struct file *filp)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int ret;
        struct iattr newattrs;
 
@@ -62,13 +63,14 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
 
        inode_lock(dentry->d_inode);
        /* Note any delegations or leases have already been broken: */
-       ret = notify_change(mnt_userns, dentry, &newattrs, NULL);
+       ret = notify_change(idmap, dentry, &newattrs, NULL);
        inode_unlock(dentry->d_inode);
        return ret;
 }
 
 long vfs_truncate(const struct path *path, loff_t length)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        struct inode *inode;
        long error;
@@ -85,7 +87,8 @@ long vfs_truncate(const struct path *path, loff_t length)
        if (error)
                goto out;
 
-       mnt_userns = mnt_user_ns(path->mnt);
+       idmap = mnt_idmap(path->mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        error = inode_permission(mnt_userns, inode, MAY_WRITE);
        if (error)
                goto mnt_drop_write_and_out;
@@ -108,7 +111,7 @@ long vfs_truncate(const struct path *path, loff_t length)
 
        error = security_path_truncate(path);
        if (!error)
-               error = do_truncate(mnt_userns, path->dentry, length, 0, NULL);
+               error = do_truncate(idmap, path->dentry, length, 0, NULL);
 
 put_write_and_out:
        put_write_access(inode);
@@ -190,7 +193,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
        sb_start_write(inode->i_sb);
        error = security_file_truncate(f.file);
        if (!error)
-               error = do_truncate(file_mnt_user_ns(f.file), dentry, length,
+               error = do_truncate(file_mnt_idmap(f.file), dentry, length,
                                    ATTR_MTIME | ATTR_CTIME, f.file);
        sb_end_write(inode->i_sb);
 out_putf:
@@ -603,7 +606,7 @@ 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(mnt_user_ns(path->mnt), path->dentry,
+       error = notify_change(mnt_idmap(path->mnt), path->dentry,
                              &newattrs, &delegated_inode);
 out_unlock:
        inode_unlock(inode);
@@ -701,6 +704,7 @@ static inline bool setattr_vfsgid(struct iattr *attr, kgid_t kgid)
 
 int chown_common(const struct path *path, uid_t user, gid_t group)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns, *fs_userns;
        struct inode *inode = path->dentry->d_inode;
        struct inode *delegated_inode = NULL;
@@ -712,7 +716,8 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
        uid = make_kuid(current_user_ns(), user);
        gid = make_kgid(current_user_ns(), group);
 
-       mnt_userns = mnt_user_ns(path->mnt);
+       idmap = mnt_idmap(path->mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        fs_userns = i_user_ns(inode);
 
 retry_deleg:
@@ -733,7 +738,7 @@ retry_deleg:
                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,
+               error = notify_change(idmap, path->dentry, &newattrs,
                                      &delegated_inode);
        inode_unlock(inode);
        if (delegated_inode) {
@@ -1064,7 +1069,7 @@ struct file *dentry_create(const struct path *path, int flags, umode_t mode,
        if (IS_ERR(f))
                return f;
 
-       error = vfs_create(mnt_user_ns(path->mnt),
+       error = vfs_create(mnt_idmap(path->mnt),
                           d_inode(path->dentry->d_parent),
                           path->dentry, mode, true);
        if (!error)
index 1df7f850ff3bb2a0d9af356cbd4beaa4cb59a4a5..ff89454b07fcfc0677f87f620ae829c884c5101d 100644 (file)
@@ -141,13 +141,13 @@ static inline int ovl_do_notify_change(struct ovl_fs *ofs,
                                       struct dentry *upperdentry,
                                       struct iattr *attr)
 {
-       return notify_change(ovl_upper_mnt_userns(ofs), upperdentry, attr, NULL);
+       return notify_change(ovl_upper_mnt_idmap(ofs), upperdentry, attr, NULL);
 }
 
 static inline int ovl_do_rmdir(struct ovl_fs *ofs,
                               struct inode *dir, struct dentry *dentry)
 {
-       int err = vfs_rmdir(ovl_upper_mnt_userns(ofs), dir, dentry);
+       int err = vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry);
 
        pr_debug("rmdir(%pd2) = %i\n", dentry, err);
        return err;
@@ -156,7 +156,7 @@ static inline int ovl_do_rmdir(struct ovl_fs *ofs,
 static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir,
                                struct dentry *dentry)
 {
-       int err = vfs_unlink(ovl_upper_mnt_userns(ofs), dir, dentry, NULL);
+       int err = vfs_unlink(ovl_upper_mnt_idmap(ofs), dir, dentry, NULL);
 
        pr_debug("unlink(%pd2) = %i\n", dentry, err);
        return err;
@@ -165,7 +165,8 @@ static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir,
 static inline int ovl_do_link(struct ovl_fs *ofs, struct dentry *old_dentry,
                              struct inode *dir, struct dentry *new_dentry)
 {
-       int err = vfs_link(old_dentry, ovl_upper_mnt_userns(ofs), dir, new_dentry, NULL);
+       int err = vfs_link(old_dentry, ovl_upper_mnt_idmap(ofs), dir,
+                          new_dentry, NULL);
 
        pr_debug("link(%pd2, %pd2) = %i\n", old_dentry, new_dentry, err);
        return err;
@@ -175,7 +176,7 @@ static inline int ovl_do_create(struct ovl_fs *ofs,
                                struct inode *dir, struct dentry *dentry,
                                umode_t mode)
 {
-       int err = vfs_create(ovl_upper_mnt_userns(ofs), dir, dentry, mode, true);
+       int err = vfs_create(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, true);
 
        pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err);
        return err;
@@ -185,7 +186,7 @@ static inline int ovl_do_mkdir(struct ovl_fs *ofs,
                               struct inode *dir, struct dentry *dentry,
                               umode_t mode)
 {
-       int err = vfs_mkdir(ovl_upper_mnt_userns(ofs), dir, dentry, mode);
+       int err = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode);
        pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, err);
        return err;
 }
@@ -194,7 +195,7 @@ static inline int ovl_do_mknod(struct ovl_fs *ofs,
                               struct inode *dir, struct dentry *dentry,
                               umode_t mode, dev_t dev)
 {
-       int err = vfs_mknod(ovl_upper_mnt_userns(ofs), dir, dentry, mode, dev);
+       int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev);
 
        pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err);
        return err;
@@ -204,7 +205,7 @@ static inline int ovl_do_symlink(struct ovl_fs *ofs,
                                 struct inode *dir, struct dentry *dentry,
                                 const char *oldname)
 {
-       int err = vfs_symlink(ovl_upper_mnt_userns(ofs), dir, dentry, oldname);
+       int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname);
 
        pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err);
        return err;
@@ -298,10 +299,10 @@ static inline int ovl_do_rename(struct ovl_fs *ofs, struct inode *olddir,
 {
        int err;
        struct renamedata rd = {
-               .old_mnt_userns = ovl_upper_mnt_userns(ofs),
+               .old_mnt_idmap  = ovl_upper_mnt_idmap(ofs),
                .old_dir        = olddir,
                .old_dentry     = olddentry,
-               .new_mnt_userns = ovl_upper_mnt_userns(ofs),
+               .new_mnt_idmap  = ovl_upper_mnt_idmap(ofs),
                .new_dir        = newdir,
                .new_dentry     = newdentry,
                .flags          = flags,
@@ -319,7 +320,7 @@ static inline int ovl_do_rename(struct ovl_fs *ofs, struct inode *olddir,
 static inline int ovl_do_whiteout(struct ovl_fs *ofs,
                                  struct inode *dir, struct dentry *dentry)
 {
-       int err = vfs_whiteout(ovl_upper_mnt_userns(ofs), dir, dentry);
+       int err = vfs_whiteout(ovl_upper_mnt_idmap(ofs), dir, dentry);
        pr_debug("whiteout(%pd2) = %i\n", dentry, err);
        return err;
 }
@@ -328,7 +329,7 @@ static inline struct file *ovl_do_tmpfile(struct ovl_fs *ofs,
                                          struct dentry *dentry, umode_t mode)
 {
        struct path path = { .mnt = ovl_upper_mnt(ofs), .dentry = dentry };
-       struct file *file = vfs_tmpfile_open(ovl_upper_mnt_userns(ofs), &path, mode,
+       struct file *file = vfs_tmpfile_open(ovl_upper_mnt_idmap(ofs), &path, mode,
                                        O_LARGEFILE | O_WRONLY, current_cred());
        int err = PTR_ERR_OR_ZERO(file);
 
index e1af8f66069843c04ab3b4e1c1be384d965a7ecb..a6a9235c6168247d62483f6864f2cf8b7850183c 100644 (file)
@@ -95,6 +95,11 @@ static inline struct user_namespace *ovl_upper_mnt_userns(struct ovl_fs *ofs)
        return mnt_user_ns(ovl_upper_mnt(ofs));
 }
 
+static inline struct mnt_idmap *ovl_upper_mnt_idmap(struct ovl_fs *ofs)
+{
+       return mnt_idmap(ovl_upper_mnt(ofs));
+}
+
 static inline struct ovl_fs *OVL_FS(struct super_block *sb)
 {
        return (struct ovl_fs *)sb->s_fs_info;
index 39f3560176359091a044a93e24096ef55b40fc76..5f71e2209e6fad89e04b52625618faca0407d608 100644 (file)
@@ -62,7 +62,7 @@ int vfs_utimes(const struct path *path, struct timespec64 *times)
        }
 retry_deleg:
        inode_lock(inode);
-       error = notify_change(mnt_user_ns(path->mnt), path->dentry, &newattrs,
+       error = notify_change(mnt_idmap(path->mnt), path->dentry, &newattrs,
                              &delegated_inode);
        inode_unlock(inode);
        if (delegated_inode) {
index 066555ad1bf810b7a57437cc2b3607c9ec5d52f9..7aa302d2ce39b0b79e700be3c3e71edfcb7b5fa9 100644 (file)
@@ -1944,36 +1944,36 @@ bool inode_owner_or_capable(struct user_namespace *mnt_userns,
 /*
  * VFS helper functions..
  */
-int vfs_create(struct user_namespace *, struct inode *,
+int vfs_create(struct mnt_idmap *, struct inode *,
               struct dentry *, umode_t, bool);
-int vfs_mkdir(struct user_namespace *, struct inode *,
+int vfs_mkdir(struct mnt_idmap *, struct inode *,
              struct dentry *, umode_t);
-int vfs_mknod(struct user_namespace *, struct inode *, struct dentry *,
+int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
               umode_t, dev_t);
-int vfs_symlink(struct user_namespace *, struct inode *,
+int vfs_symlink(struct mnt_idmap *, struct inode *,
                struct dentry *, const char *);
-int vfs_link(struct dentry *, struct user_namespace *, struct inode *,
+int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *,
             struct dentry *, struct inode **);
-int vfs_rmdir(struct user_namespace *, struct inode *, struct dentry *);
-int vfs_unlink(struct user_namespace *, struct inode *, struct dentry *,
+int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *);
+int vfs_unlink(struct mnt_idmap *, struct inode *, struct dentry *,
               struct inode **);
 
 /**
  * struct renamedata - contains all information required for renaming
- * @old_mnt_userns:    old user namespace of the mount the inode was found from
+ * @old_mnt_idmap:     idmap of the old mount the inode was found from
  * @old_dir:           parent of source
  * @old_dentry:                source
- * @new_mnt_userns:    new user namespace of the mount the inode was found from
+ * @new_mnt_idmap:     idmap of the new mount the inode was found from
  * @new_dir:           parent of destination
  * @new_dentry:                destination
  * @delegated_inode:   returns an inode needing a delegation break
  * @flags:             rename flags
  */
 struct renamedata {
-       struct user_namespace *old_mnt_userns;
+       struct mnt_idmap *old_mnt_idmap;
        struct inode *old_dir;
        struct dentry *old_dentry;
-       struct user_namespace *new_mnt_userns;
+       struct mnt_idmap *new_mnt_idmap;
        struct inode *new_dir;
        struct dentry *new_dentry;
        struct inode **delegated_inode;
@@ -1982,14 +1982,14 @@ struct renamedata {
 
 int vfs_rename(struct renamedata *);
 
-static inline int vfs_whiteout(struct user_namespace *mnt_userns,
+static inline int vfs_whiteout(struct mnt_idmap *idmap,
                               struct inode *dir, struct dentry *dentry)
 {
-       return vfs_mknod(mnt_userns, dir, dentry, S_IFCHR | WHITEOUT_MODE,
+       return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE,
                         WHITEOUT_DEV);
 }
 
-struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
+struct file *vfs_tmpfile_open(struct mnt_idmap *idmap,
                        const struct path *parentpath,
                        umode_t mode, int open_flag, const struct cred *cred);
 
@@ -2746,7 +2746,7 @@ static inline bool is_idmapped_mnt(const struct vfsmount *mnt)
 }
 
 extern long vfs_truncate(const struct path *, loff_t);
-int do_truncate(struct user_namespace *, struct dentry *, loff_t start,
+int do_truncate(struct mnt_idmap *, struct dentry *, loff_t start,
                unsigned int time_attrs, struct file *filp);
 extern int vfs_fallocate(struct file *file, int mode, loff_t offset,
                        loff_t len);
@@ -2901,7 +2901,7 @@ static inline int bmap(struct inode *inode,  sector_t *block)
 }
 #endif
 
-int notify_change(struct user_namespace *, struct dentry *,
+int notify_change(struct mnt_idmap *, struct dentry *,
                  struct iattr *, struct inode **);
 int inode_permission(struct user_namespace *, struct inode *, int);
 int generic_permission(struct user_namespace *, struct inode *, int);
index d09aa1c1e3e653b70e3788d0359517bcb92982b9..4b78095fe77930bb9bd55c7a3265acc0029bf078 100644 (file)
@@ -979,7 +979,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
                err = -ENOENT;
        } else {
                ihold(inode);
-               err = vfs_unlink(&init_user_ns, d_inode(dentry->d_parent),
+               err = vfs_unlink(&nop_mnt_idmap, d_inode(dentry->d_parent),
                                 dentry, NULL);
        }
        dput(dentry);
index f0c2293f1d3b8bd409cff9902d4c2f48e4bb151b..81ff9829899639d12be13922d284216c32b64397 100644 (file)
@@ -1190,7 +1190,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
        unsigned int new_hash, old_hash = sk->sk_hash;
        struct unix_sock *u = unix_sk(sk);
        struct net *net = sock_net(sk);
-       struct user_namespace *ns; // barf...
+       struct mnt_idmap *idmap;
        struct unix_address *addr;
        struct dentry *dentry;
        struct path parent;
@@ -1217,10 +1217,10 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
        /*
         * All right, let's create it.
         */
-       ns = mnt_user_ns(parent.mnt);
+       idmap = mnt_idmap(parent.mnt);
        err = security_path_mknod(&parent, dentry, mode, 0);
        if (!err)
-               err = vfs_mknod(ns, d_inode(parent.dentry), dentry, mode, 0);
+               err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0);
        if (err)
                goto out_path;
        err = mutex_lock_interruptible(&u->bindlock);
@@ -1245,7 +1245,7 @@ out_unlock:
        err = -EINVAL;
 out_unlink:
        /* failed after successful mknod?  unlink what we'd created... */
-       vfs_unlink(ns, d_inode(parent.dentry), dentry, NULL);
+       vfs_unlink(idmap, d_inode(parent.dentry), dentry, NULL);
 out_path:
        done_path_create(&parent, dentry);
 out:
index 92331053dba3b6bfff23a4050a6d0ecd7bae40d3..7bd76b9e0f9841c62916ab09d7052929c35ba86a 100644 (file)
@@ -826,7 +826,7 @@ out:
 
 SEC("kprobe/vfs_link")
 int BPF_KPROBE(kprobe__vfs_link,
-              struct dentry* old_dentry, struct user_namespace *mnt_userns,
+              struct dentry* old_dentry, struct mnt_idmap *idmap,
               struct inode* dir, struct dentry* new_dentry,
               struct inode** delegated_inode)
 {