[PATCH v8 03/11] fs: make do_mkdirat() take struct filename

Dmitry Kadashev
2021-07-07T12:28:08Z

Pass in the struct filename pointers instead of the user string, and
update the three callers to do the same. This is heavily based on
commit dbea8d345177 ("fs: make do_renameat2() take struct filename").

This behaves like do_unlinkat() and do_renameat2().

Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
---
fs/internal.h | 1 +
fs/namei.c | 26 +++++++++++++++++++-------
2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 6aeae7ef3380..848e165ef0f1 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -77,6 +77,7 @@ long do_unlinkat(int dfd, struct filename *name);
int may_linkat(struct user_namespace *mnt_userns, struct path *link);
int do_renameat2(int olddfd, struct filename *oldname, int newdfd,
struct filename *newname, unsigned int flags);
+long do_mkdirat(int dfd, struct filename *name, umode_t mode);

/*
* namespace.c
diff --git a/fs/namei.c b/fs/namei.c
index 2995b3695724..54d5f19ee1ce 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3563,7 +3563,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
return file;
}

-static struct dentry *filename_create(int dfd, struct filename *name,
+static struct dentry *__filename_create(int dfd, struct filename *name,
struct path *path, unsigned int lookup_flags)
{
struct dentry *dentry = ERR_PTR(-EEXIST);
@@ -3579,7 +3579,7 @@ static struct dentry *filename_create(int dfd, struct filename *name,
*/
lookup_flags &= LOOKUP_REVAL;

- error = filename_parentat(dfd, name, lookup_flags, path, &last, &type);
+ error = __filename_parentat(dfd, name, lookup_flags, path, &last, &type);
if (error)
return ERR_PTR(error);

@@ -3632,6 +3632,15 @@ static struct dentry *filename_create(int dfd, struct filename *name,
return dentry;
}

+static inline struct dentry *filename_create(int dfd, struct filename *name,
+ struct path *path, unsigned int lookup_flags)
+{
+ struct dentry *res = __filename_create(dfd, name, path, lookup_flags);
+
+ putname(name);
+ return res;
+}
+
struct dentry *kern_path_create(int dfd, const char *pathname,
struct path *path, unsigned int lookup_flags)
{
@@ -3822,7 +3831,7 @@ int vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
}
EXPORT_SYMBOL(vfs_mkdir);

-static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
+long do_mkdirat(int dfd, struct filename *name, umode_t mode)
{
struct dentry *dentry;
struct path path;
@@ -3830,9 +3839,10 @@ static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
unsigned int lookup_flags = LOOKUP_DIRECTORY;

retry:
- dentry = user_path_create(dfd, pathname, &path, lookup_flags);
+ dentry = __filename_create(dfd, name, &path, lookup_flags);
+ error = PTR_ERR(dentry);
if (IS_ERR(dentry))
- return PTR_ERR(dentry);
+ goto out_putname;

if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
@@ -3848,17 +3858,19 @@ static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
+out_putname:
+ putname(name);
return error;
}

SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
{
- return do_mkdirat(dfd, pathname, mode);
+ return do_mkdirat(dfd, getname(pathname), mode);
}

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
{
- return do_mkdirat(AT_FDCWD, pathname, mode);
+ return do_mkdirat(AT_FDCWD, getname(pathname), mode);
}

/**
--
2.30.2