[Virtio-fs] [PATCH] virtiofsd: Fix xattr operations

Vivek Goyal vgoyal at redhat.com
Fri Jan 10 16:13:34 UTC 2020


On Fri, Jan 10, 2020 at 10:07:22AM +0900, Misono Tomohiro wrote:
[..]
> @@ -2345,6 +2347,7 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
>      ssize_t ret;
>      int saverr;
>      int fd = -1;
> +    bool dir_changed = false;
>  
>      inode = lo_inode(req, ino);
>      if (!inode) {

> @@ -2360,16 +2363,20 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
>      fuse_log(FUSE_LOG_DEBUG, "lo_getxattr(ino=%" PRIu64 ", name=%s size=%zd)\n",
>               ino, name, size);
>  
> -    if (inode->is_symlink) {
> -        /* Sorry, no race free way to getxattr on symlink. */
> -        saverr = EPERM;
> -        goto out;
> -    }
> -

What was the race previously on symlinks and how does this code get rid
of that race?

>      sprintf(procname, "%i", inode->fd);
> -    fd = openat(lo->proc_self_fd, procname, O_RDONLY);
> -    if (fd < 0) {
> -        goto out_err;
> +    if (inode->is_regular) {
> +        fd = openat(lo->proc_self_fd, procname, O_RDONLY);
> +        if (fd < 0) {
> +          goto out_err;
> +        }
> +    } else {
> +        ret = fchdir(lo->proc_self_fd);
> +        if (ret < 0) {
> +            /* should not happen */
> +            fuse_log(FUSE_LOG_ERR, "lo_getxattr: fail fchdir to proc_self_fd\n");
> +            goto out_err;
> +        }
> +        dir_changed = true;
>      }
>  
>      if (size) {
> @@ -2378,7 +2385,11 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
>              goto out_err;
>          }
>  
> -        ret = fgetxattr(fd, name, value, size);
> +        if (inode->is_regular) {
> +            ret = fgetxattr(fd, name, value, size);
> +        } else {
> +            ret = getxattr(procname, name, value, size);
> +        }

Do we need "lgetxattr()" instead of "getxattr()" for symlinks?

Say I have following setup.

foo-symlink -> foo.txt

Now lo_lookup(foo-symlink.txt, O_PATH | O_NOFOLLOW), will get fd on
symlink, say 3. And proc should show something similar.

And /proc/self/fd/3 -> /foo-symlink.txt

Now if we do getxattr(3), will it not resolve symlinks and get xattr value
from "foo.txt" instead?

I think in practice that's not happening. So I am misunderstanding
something. What's that?

Thanks
Vivek




More information about the Virtio-fs mailing list