In order to handle idmapped mounts we will extend the vfs rename helper to
take two new arguments in follow up patches. Since this operations already
takes a bunch of arguments add a simple struct renamedata (based on struct
nameidata) and make the current helper to use it before we extend it.

Cc: Christoph Hellwig <h...@lst.de>
Cc: David Howells <dhowe...@redhat.com>
Cc: Al Viro <v...@zeniv.linux.org.uk>
Cc: linux-fsde...@vger.kernel.org
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
/* v2 */
unchanged
---
 fs/cachefiles/namei.c    |  9 +++++++--
 fs/ecryptfs/inode.c      | 10 +++++++---
 fs/namei.c               | 21 +++++++++++++++------
 fs/nfsd/vfs.c            |  8 +++++++-
 fs/overlayfs/overlayfs.h |  9 ++++++++-
 include/linux/fs.h       | 12 +++++++++++-
 6 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index ecc8ecbbfa5a..7b987de0babe 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -412,9 +412,14 @@ static int cachefiles_bury_object(struct cachefiles_cache 
*cache,
        if (ret < 0) {
                cachefiles_io_error(cache, "Rename security error %d", ret);
        } else {
+               struct renamedata rd = {
+                       .old_dir        = d_inode(dir),
+                       .old_dentry     = rep,
+                       .new_dir        = d_inode(cache->graveyard),
+                       .new_dentry     = grave,
+               };
                trace_cachefiles_rename(object, rep, grave, why);
-               ret = vfs_rename(d_inode(dir), rep,
-                                d_inode(cache->graveyard), grave, NULL, 0);
+               ret = vfs_rename(&rd);
                if (ret != 0 && ret != -ENOMEM)
                        cachefiles_io_error(cache,
                                            "Rename failed with error %d", ret);
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index d98448c75051..838949ede439 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -590,6 +590,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
        struct dentry *lower_new_dir_dentry;
        struct dentry *trap;
        struct inode *target_inode;
+       struct renamedata rd = {};
 
        if (flags)
                return -EINVAL;
@@ -619,9 +620,12 @@ ecryptfs_rename(struct inode *old_dir, struct dentry 
*old_dentry,
                rc = -ENOTEMPTY;
                goto out_lock;
        }
-       rc = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
-                       d_inode(lower_new_dir_dentry), lower_new_dentry,
-                       NULL, 0);
+
+       rd.old_dir      = d_inode(lower_old_dir_dentry);
+       rd.old_dentry   = lower_old_dentry;
+       rd.new_dir      = d_inode(lower_new_dir_dentry);
+       rd.new_dentry   = lower_new_dentry;
+       rc = vfs_rename(&rd);
        if (rc)
                goto out_lock;
        if (target_inode)
diff --git a/fs/namei.c b/fs/namei.c
index 4dc842d1cd3a..0a2450de83bb 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4256,12 +4256,15 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, 
const char __user *, newname
  *        ->i_mutex on parents, which works but leads to some truly excessive
  *        locking].
  */
-int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-              struct inode *new_dir, struct dentry *new_dentry,
-              struct inode **delegated_inode, unsigned int flags)
+int vfs_rename(struct renamedata *rd)
 {
        int error;
        struct user_namespace *user_ns = &init_user_ns;
+       struct inode *old_dir = rd->old_dir, *new_dir = rd->new_dir;
+       struct dentry *old_dentry = rd->old_dentry,
+                     *new_dentry = rd->new_dentry;
+       struct inode **delegated_inode = rd->delegated_inode;
+       unsigned int flags = rd->flags;
        bool is_dir = d_is_dir(old_dentry);
        struct inode *source = old_dentry->d_inode;
        struct inode *target = new_dentry->d_inode;
@@ -4385,6 +4388,7 @@ EXPORT_SYMBOL(vfs_rename);
 static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,
                        const char __user *newname, unsigned int flags)
 {
+       struct renamedata rd;
        struct dentry *old_dentry, *new_dentry;
        struct dentry *trap;
        struct path old_path, new_path;
@@ -4490,9 +4494,14 @@ static int do_renameat2(int olddfd, const char __user 
*oldname, int newdfd,
                                     &new_path, new_dentry, flags);
        if (error)
                goto exit5;
-       error = vfs_rename(old_path.dentry->d_inode, old_dentry,
-                          new_path.dentry->d_inode, new_dentry,
-                          &delegated_inode, flags);
+
+       rd.old_dir         = old_path.dentry->d_inode;
+       rd.old_dentry      = old_dentry;
+       rd.new_dir         = new_path.dentry->d_inode;
+       rd.new_dentry      = new_dentry;
+       rd.delegated_inode = &delegated_inode;
+       rd.flags           = flags;
+       error = vfs_rename(&rd);
 exit5:
        dput(new_dentry);
 exit4:
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 9a0e0e5b34f5..3d7a8cd61098 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1787,7 +1787,13 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, 
char *fname, int flen,
                has_cached = true;
                goto out_dput_old;
        } else {
-               host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL, 0);
+               struct renamedata rd = {
+                       .old_dir        = fdir,
+                       .old_dentry     = odentry,
+                       .new_dir        = tdir,
+                       .new_dentry     = ndentry,
+               };
+               host_err = vfs_rename(&rd);
                if (!host_err) {
                        host_err = commit_metadata(tfhp);
                        if (!host_err)
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index bf26fb3fa2c1..73da8710b0f0 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -212,9 +212,16 @@ static inline int ovl_do_rename(struct inode *olddir, 
struct dentry *olddentry,
                                unsigned int flags)
 {
        int err;
+       struct renamedata rd = {
+               .old_dir        = olddir,
+               .old_dentry     = olddentry,
+               .new_dir        = newdir,
+               .new_dentry     = newdentry,
+               .flags          = flags,
+       };
 
        pr_debug("rename(%pd2, %pd2, 0x%x)\n", olddentry, newdentry, flags);
-       err = vfs_rename(olddir, olddentry, newdir, newdentry, NULL, flags);
+       err = vfs_rename(&rd);
        if (err) {
                pr_debug("...rename(%pd2, %pd2, ...) = %i\n",
                         olddentry, newdentry, err);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 05a228ce767a..22c0ab9d0fcf 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1756,7 +1756,17 @@ extern int vfs_symlink(struct inode *, struct dentry *, 
const char *);
 extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct 
inode **);
 extern int vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct 
dentry *, struct inode **, unsigned int);
+
+struct renamedata {
+       struct inode *old_dir;
+       struct dentry *old_dentry;
+       struct inode *new_dir;
+       struct dentry *new_dentry;
+       struct inode **delegated_inode;
+       unsigned int flags;
+} __randomize_layout;
+
+extern int vfs_rename(struct renamedata *);
 
 static inline int vfs_whiteout(struct inode *dir, struct dentry *dentry)
 {
-- 
2.29.2

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to