On Fri, Dec 10, 2021 at 10:51:45AM +0800, JeffleXu wrote:
> 
> 
> On 12/10/21 3:33 AM, Vivek Goyal wrote:
> > On Tue, Nov 02, 2021 at 01:56:41PM +0800, Jeffle Xu wrote:
> >> For passthrough, it passes corresponding ioctls to host directly.
> >>
> >> Currently only these ioctls that handling persistent inode flags, i.e.,
> >> FS_IOC_[G|S]ETFLAGS and FS_IOC_FS[G|S]ETXATTR are supported for security
> >> concern, though it's implemented in a quite general way, so that we can
> >> expand the scope of allowed ioctls if it is really needed later.
> >>
> >> Signed-off-by: Jeffle Xu <[email protected]>
> >> ---
> >>  tools/virtiofsd/passthrough_ll.c      | 65 +++++++++++++++++++++++++++
> >>  tools/virtiofsd/passthrough_seccomp.c |  1 +
> >>  2 files changed, 66 insertions(+)
> >>
> >> diff --git a/tools/virtiofsd/passthrough_ll.c 
> >> b/tools/virtiofsd/passthrough_ll.c
> >> index b7c1fa71b5..2768497be4 100644
> >> --- a/tools/virtiofsd/passthrough_ll.c
> >> +++ b/tools/virtiofsd/passthrough_ll.c
> >> @@ -47,6 +47,7 @@
> >>  #include <dirent.h>
> >>  #include <pthread.h>
> >>  #include <sys/file.h>
> >> +#include <sys/ioctl.h>
> >>  #include <sys/mount.h>
> >>  #include <sys/prctl.h>
> >>  #include <sys/resource.h>
> >> @@ -54,6 +55,7 @@
> >>  #include <sys/wait.h>
> >>  #include <sys/xattr.h>
> >>  #include <syslog.h>
> >> +#include <linux/fs.h>
> >>  
> >>  #include "qemu/cutils.h"
> >>  #include "passthrough_helpers.h"
> >> @@ -2188,6 +2190,68 @@ out:
> >>      fuse_reply_err(req, saverr);
> >>  }
> >>  
> >> +
> >> +static void lo_ioctl(fuse_req_t req, fuse_ino_t ino, unsigned int cmd,
> >> +                     void *arg, struct fuse_file_info *fi,
> >> +                     unsigned flags, const void *in_buf,
> >> +                     size_t in_bufsz, size_t out_bufsz)
> >> +{
> >> +    int res, dir;
> >> +    int fd = lo_fi_fd(req, fi);
> >> +    int saverr = ENOSYS;
> >> +    void *buf = NULL;
> >> +    size_t size = 0;
> >> +
> >> +    fuse_log(FUSE_LOG_DEBUG, "lo_ioctl(ino=%" PRIu64 ", cmd=0x%x, 
> >> flags=0x%x, "
> >> +            "in_bufsz = %lu, out_bufsz = %lu)\n",
> >> +            ino, cmd, flags, in_bufsz, out_bufsz);
> >> +
> >> +    if (!(cmd == FS_IOC_SETFLAGS || cmd == FS_IOC_GETFLAGS ||
> >> +          cmd == FS_IOC_FSSETXATTR || cmd == FS_IOC_FSGETXATTR)) {
> >> +        goto out;
> > 
> > Good that you allowed only two operations. Still I think people might
> > have concern about all the inode attrs and whether it is safe to
> > allow that. For example immutable flag. Now even host can't delete
> > that file without first clearing that flag. 
> 
> Yes, this will be an issue.
> 
> > I think it is doable
> > just that involves extra step.
> > 
> > So we probably might have to block certain attrs if it becomes an
> > issue or make it configurable.
> 
> Currently fuse kernel module only requires that virtiofsd shall support
> the set flag path (FS_IOC_SETFLAGS/FS_IOC_FSSETXATTR), so that users
> inside guest are able to set/clear FS_XFLAG_DAX flag. For the set flag
> path, maybe we could support modifying FS_XFLAG_DAX flag first for the
> security concern?

I think right now limiting ioctl operations to FS_XFLAG_DAX is not
a bad idea. That's what we need for now. Others can be opened when
people need it.

> 
> The get flag path(FS_IOC_GETFLAGS/FS_IOC_FSGETXATTR) is not strongly
> required currently, since the DAX flag is totally constructed by
> virtiofsd now. The use case of the get flag path may be like, users
> inside guest may want to query the FS_XFLAG_DAX flag after setting
> FS_XFLAG_DAX flag previously. The get flag path may also expose the file
> attr of the host file to the guest, and thus maybe we shall also only
> support quering FS_XFLAG_DAX flag as the first step.

Querying FS_XFLAG_DAX is fine. And I agreed that it is needed because
guest might want to query it.

So let us support both setting and querying FS_XFLAG_DAX and block other
operations for now.

> 
> 
> > 
> >> +    }
> >> +
> >> +    /* unrestricted ioctl is not supported yet */
> >> +    if (flags & FUSE_IOCTL_UNRESTRICTED) {
> >> +        goto out;
> >> +    }
> >> +
> >> +    dir = _IOC_DIR(cmd);
> >> +
> >> +    if (dir & _IOC_READ) {
> >> +        size = out_bufsz;
> >> +        buf = malloc(size);
> >> +        if (!buf) {
> >> +            goto out_err;
> >> +        }
> >> +
> >> +        if (dir & _IOC_WRITE) {
> >> +            memcpy(buf, in_buf, size);
> >> +        }
> >> +
> >> +        res = ioctl(fd, cmd, buf);
> >> +    } else if (dir & _IOC_WRITE) {
> >> +        res = ioctl(fd, cmd, in_buf);
> >> +    } else {
> >> +        res = ioctl(fd, cmd, arg);
> >> +    }
> > 
> > I do not understand this if block. So if _IOC_READ and _IOC_WRITE
> > is not set, then we just send "arg" as third argument. Can you
> > shed some light on how this third argument works for file attr
> > flags. 
> 
> In theory ioctl could be neither _IOC_READ nor _IOC_WRITE. I implement
> this if block just for the completeness of the logic for ioctl support.
> It doesn't matter with the file attr though.
> 
> 
> > I am assuming that "lsattr" will use the _IOC_READ path,
> > while chattr will use "_IOC_WRITE" path? If that's the case,
> > as of now third condition is not even required. Until and unless
> > we are supporting more ioctls.
> > 
> 
> Sure, I can remove this if block for now.

Sounds good. Let somebody else add it later when need be. For now, we 
can probably focus on FS_XFLAG_DAX attr only. And put a comment in code
explaining this restriction.

Vivek

_______________________________________________
Virtio-fs mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/virtio-fs

Reply via email to