diff options
author | Mateusz Guzik <mjguzik@gmail.com> | 2024-06-04 17:52:55 +0200 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2024-06-05 17:03:56 +0200 |
commit | 969ce92da3112e05d1a70c344f8740a85e933f2e (patch) | |
tree | 7d985eb66b5569ebcb8cf1146339fa7e5bd2941b | |
parent | ca86a5d2f9feed16e11023891c8c70aa57ced24e (diff) |
vfs: stop using user_path_at_empty in do_readlinkat
It is the only consumer and it saddles getname_flags with an argument set
to NULL by everyone else.
Instead the routine can do the empty check on its own.
Then user_path_at_empty can get retired and getname_flags can lose the
argument.
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Link: https://lore.kernel.org/r/20240604155257.109500-2-mjguzik@gmail.com
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
-rw-r--r-- | fs/stat.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/stat.c b/fs/stat.c index 70bd3e888cfa..7f7861544500 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -488,34 +488,39 @@ static int do_readlinkat(int dfd, const char __user *pathname, char __user *buf, int bufsiz) { struct path path; + struct filename *name; int error; - int empty = 0; unsigned int lookup_flags = LOOKUP_EMPTY; if (bufsiz <= 0) return -EINVAL; retry: - error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty); - if (!error) { - struct inode *inode = d_backing_inode(path.dentry); + name = getname_flags(pathname, lookup_flags, NULL); + error = filename_lookup(dfd, name, lookup_flags, &path, NULL); + if (unlikely(error)) { + putname(name); + return error; + } - error = empty ? -ENOENT : -EINVAL; - /* - * AFS mountpoints allow readlink(2) but are not symlinks - */ - if (d_is_symlink(path.dentry) || inode->i_op->readlink) { - error = security_inode_readlink(path.dentry); - if (!error) { - touch_atime(&path); - error = vfs_readlink(path.dentry, buf, bufsiz); - } - } - path_put(&path); - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; - goto retry; + /* + * AFS mountpoints allow readlink(2) but are not symlinks + */ + if (d_is_symlink(path.dentry) || + d_backing_inode(path.dentry)->i_op->readlink) { + error = security_inode_readlink(path.dentry); + if (!error) { + touch_atime(&path); + error = vfs_readlink(path.dentry, buf, bufsiz); } + } else { + error = (name->name[0] == '\0') ? -ENOENT : -EINVAL; + } + path_put(&path); + putname(name); + if (retry_estale(error, lookup_flags)) { + lookup_flags |= LOOKUP_REVAL; + goto retry; } return error; } |