fs: make do_renameat2() take struct filename
authorJens Axboe <axboe@kernel.dk>
Sat, 26 Sep 2020 23:20:17 +0000 (17:20 -0600)
committerJens Axboe <axboe@kernel.dk>
Wed, 9 Dec 2020 19:03:59 +0000 (12:03 -0700)
Pass in the struct filename pointers instead of the user string, and
update the three callers to do the same.

This behaves like do_unlinkat(), which also takes a filename struct and
puts it when it is done. Converting callers is then trivial.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/internal.h
fs/namei.c

index a7cd0f6..6fd14ea 100644 (file)
@@ -78,6 +78,8 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 long do_rmdir(int dfd, struct filename *name);
 long do_unlinkat(int dfd, struct filename *name);
 int may_linkat(struct path *link);
+int do_renameat2(int olddfd, struct filename *oldname, int newdfd,
+                struct filename *newname, unsigned int flags);
 
 /*
  * namespace.c
index d4a6dd7..03d0e11 100644 (file)
@@ -4346,8 +4346,8 @@ out:
 }
 EXPORT_SYMBOL(vfs_rename);
 
-static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,
-                       const char __user *newname, unsigned int flags)
+int do_renameat2(int olddfd, struct filename *from, int newdfd,
+                struct filename *to, unsigned int flags)
 {
        struct dentry *old_dentry, *new_dentry;
        struct dentry *trap;
@@ -4355,32 +4355,30 @@ static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,
        struct qstr old_last, new_last;
        int old_type, new_type;
        struct inode *delegated_inode = NULL;
-       struct filename *from;
-       struct filename *to;
        unsigned int lookup_flags = 0, target_flags = LOOKUP_RENAME_TARGET;
        bool should_retry = false;
-       int error;
+       int error = -EINVAL;
 
        if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
-               return -EINVAL;
+               goto put_both;
 
        if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
            (flags & RENAME_EXCHANGE))
-               return -EINVAL;
+               goto put_both;
 
        if (flags & RENAME_EXCHANGE)
                target_flags = 0;
 
 retry:
-       from = filename_parentat(olddfd, getname(oldname), lookup_flags,
-                               &old_path, &old_last, &old_type);
+       from = filename_parentat(olddfd, from, lookup_flags, &old_path,
+                                       &old_last, &old_type);
        if (IS_ERR(from)) {
                error = PTR_ERR(from);
-               goto exit;
+               goto put_new;
        }
 
-       to = filename_parentat(newdfd, getname(newname), lookup_flags,
-                               &new_path, &new_last, &new_type);
+       to = filename_parentat(newdfd, to, lookup_flags, &new_path, &new_last,
+                               &new_type);
        if (IS_ERR(to)) {
                error = PTR_ERR(to);
                goto exit1;
@@ -4473,34 +4471,40 @@ exit2:
        if (retry_estale(error, lookup_flags))
                should_retry = true;
        path_put(&new_path);
-       putname(to);
 exit1:
        path_put(&old_path);
-       putname(from);
        if (should_retry) {
                should_retry = false;
                lookup_flags |= LOOKUP_REVAL;
                goto retry;
        }
-exit:
+put_both:
+       if (!IS_ERR(from))
+               putname(from);
+put_new:
+       if (!IS_ERR(to))
+               putname(to);
        return error;
 }
 
 SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
                int, newdfd, const char __user *, newname, unsigned int, flags)
 {
-       return do_renameat2(olddfd, oldname, newdfd, newname, flags);
+       return do_renameat2(olddfd, getname(oldname), newdfd, getname(newname),
+                               flags);
 }
 
 SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
                int, newdfd, const char __user *, newname)
 {
-       return do_renameat2(olddfd, oldname, newdfd, newname, 0);
+       return do_renameat2(olddfd, getname(oldname), newdfd, getname(newname),
+                               0);
 }
 
 SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname)
 {
-       return do_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
+       return do_renameat2(AT_FDCWD, getname(oldname), AT_FDCWD,
+                               getname(newname), 0);
 }
 
 int readlink_copy(char __user *buffer, int buflen, const char *link)