On Wed, 27 Jan 2021 14:14:30 +0000 Stefan Hajnoczi <stefa...@redhat.com> wrote:
> On Wed, Jan 27, 2021 at 02:01:54PM +0100, Miklos Szeredi wrote: > > On Wed, Jan 27, 2021 at 12:21 PM Stefan Hajnoczi <stefa...@redhat.com> > > wrote: > > } > > > @@ -1654,9 +1677,11 @@ static void update_open_flags(int writeback, int > > > allow_direct_io, > > > static void lo_create(fuse_req_t req, fuse_ino_t parent, const char > > > *name, > > > mode_t mode, struct fuse_file_info *fi) > > > { > > > + int open_flags = (fi->flags | O_CREAT) & ~O_NOFOLLOW; > > > int fd; > > > struct lo_data *lo = lo_data(req); > > > struct lo_inode *parent_inode; > > > + struct lo_inode *existing_inode = NULL; > > > struct fuse_entry_param e; > > > int err; > > > struct lo_cred old = {}; > > > @@ -1682,11 +1707,23 @@ static void lo_create(fuse_req_t req, fuse_ino_t > > > parent, const char *name, > > > > > > update_open_flags(lo->writeback, lo->allow_direct_io, fi); > > > > > > - fd = openat(parent_inode->fd, name, (fi->flags | O_CREAT) & > > > ~O_NOFOLLOW, > > > - mode); > > > + /* First, try to create a new file but don't open existing files */ > > > + fd = openat(parent_inode->fd, name, open_flags | O_EXCL, mode); > > > err = fd == -1 ? errno : 0; > > > + > > > lo_restore_cred(&old); > > > > > > + /* Second, open existing files if O_EXCL was not specified */ > > > + if (err == EEXIST && !(fi->flags & O_EXCL)) { > > > + existing_inode = lookup_name(req, parent, name); > > > + if (existing_inode) { > > > + fd = lo_inode_open(lo, existing_inode, open_flags); > > > + if (fd < 0) { > > > + err = -fd; > > > + } > > > + } > > > + } > > > + > > > if (!err) { > > > ssize_t fh; > > > > It's more of a mess than I thought. > > > > The problem here is there can also be a race between the open and the > > subsequent lo_do_lookup(). > > > > At this point it's probably enough to verify that fuse_entry_param > > refers to the same object as the fh (using fstat and comparing st_dev > > and st_ino). > > Can you describe the race in detail? FUSE_CREATE vs FUSE_OPEN? > FUSE_CREATE vs FUSE_CREATE? > > > Also O_CREAT open is not supposed to return ENOENT, so failure to open > > without O_CREAT (race between O_CREAT open and plain open) should at > > least translate error to ESTALE or EIO. > > Thanks, will fix. > Please wait, as explained in another mail, ENOENT can happen with O_CREAT and guest userspace should be ready to handle it. > Sstefan
pgpi9UCXNrlOP.pgp
Description: OpenPGP digital signature