[Adding CC's] On Thu, Sep 25, 2014 at 2:05 PM, Maxim Patlasov <MPatlasov@xxxxxxxxxxxxx> wrote: > In short, the problem is that fuse_release (that's usually called on last > user close(2)) sends FUSE_RELEASE to userspace and returns without waiting > for ACK from userspace. Consequently, there is a gap when user regards the > file released while userspace fuse is still working on it. An attempt to > access the file from another node leads to complicated synchronization > problems because the first node still "holds" the file. > > The patch-set resolves the problem by making fuse_release synchronous: > wait for ACK from userspace for FUSE_RELEASE if the feature is ON. > > It must be emphasized that even if the feature is enabled (i.e. fuse_release > is synchronous), nothing guarantees that fuse_release() will be called > in the context of close(2). In fact, it may happen later, on last fput(). > However, there are still a lot of use cases when close(2) is synchronous, > so the feature must be regarded as an optimization maximizing chances of > synchronous behaviour of close(2). Okay, we have the common case of close -> last-fput ->release. This being synchronous is fine. Related cases are munmap(), and weird corner cases including I/O on file descriptor being done in parallel with close() in another thread. Synchronous behavior is also fine in these cases, since the task calling the last fput() is in fact responsible for releasing the file. And then we have the uncommon cases when fput() is called from something unrelated. Take the following DoS example: malicious app creates a socket loop (sockA is sent over sockB and sockB is sent over sockA) and in addition it tacks a fuse fd onto one of the sockets. The fuse fd is implemented to block forever on release. In this case the loop will persist after the sockets are closed due to refcounting. Later, a garbage collection is triggered from a completely unrelated socket operation. This result in the unrelated task being blocked forever. The simplest way to avoid such an attack is to make the sync-release feature privileged. But even if it's privileged, the fact that ->release can take a lot of time and a completely unrelated task could be waiting for it to finish is not a good thing. So I'm wondering: could we have some way of distinguishing "good release" from "bad release"? Maybe adding an fput_sync() variant that passes an "sync" flag to ->release()? Al, Linus? Thanks, Miklos -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html