Re: [PATCH 1/3] vfs: stop using user_path_at_empty in do_readlinkat

From: Jan Kara
Date: Wed Jun 05 2024 - 11:48:45 EST


On Tue 04-06-24 17:52:55, Mateusz Guzik wrote:
> 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@xxxxxxxxx>

Looks good to me. Feel free to add:

Reviewed-by: Jan Kara <jack@xxxxxxx>

Honza

> ---
> fs/stat.c | 43 ++++++++++++++++++++++++-------------------
> 1 file 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;
> }
> --
> 2.39.2
>
--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR