> Von: Avery Pennarun <apenwarr> > An: [EMAIL PROTECTED] > Betreff: Re: Bug#339037: open(2) man page doesn't document potentia > Datum: Thu, 17 Nov 2005 10:51:34 -0500 > > On Thu, Nov 17, 2005 at 03:59:58PM +0100, Michael Kerrisk wrote: > > > > It appears you *have* to open in blocking mode in order to > > > open a leased file at all, > > > > Yes. > > > > > but that's not clear from the description. > > > > Again, I would say that's fairly clear from the man page: > > if the open() call returns (i.e., fails) with EWOULDBLOCK, > > then clearly the file was not opened. But again, it might > > help to add a little more text. > > > > > It wouldn't be so bad to open in blocking mode since a lease is > > > guaranteed > > > to be broken after a certain timeout. But a naive implementation > > > would > > > introduce a security hole since the file might be replaced by > > > surprise with a FIFO, which has no open timeout at all. > > > > I do not understand this last piece. > > The above three things tie together: if you're correct and the > lease-breaking steps are followed even with O_NONBLOCK, it's obvious that > you could *potentially* be able to open a leased file with O_NONBLOCK > eventually, by following steps like this: > > - open() -> EWOULDBLOCK > - wait a while > - open() -> success > > That's because the lease *starts* to get broken on the first open(), and > probably is finished being broken by your second or third try.
Only if the delay is longer than lease-break-time (45 secs by default, which is quite long), or the lease holder releases the lease sooner. > So the first > claim above, that you *have* to open in blocking mode, is not strictly > true. It is true for that particular open() call. Of course *anything* might happen by the time of another open() call (the lease holder might remove the leae, someone might delete the file, or even the directory containing it...) > It would be true if opening with O_NONBLOCK definitely *doesn't* ask to > start the lease breaking-steps; that's the part I thought was unclear. > (The clarification you added about it is good, assuming it's correct.) Okay. > But essentially, even if this might work eventually, it's unsafe, because > what *might* happen is this: > > - open() -> EWOULDBLOCK > - lease gets broken > - lease gets reacquired > - open() -> EWOULDBLOCK > - ... > > The only way to guarantee that you'll ever get to open the file within > some reasonable time is to open it in blocking mode. > > This might be a very common case. I know that if I was writing a > lease-using program, and I knew that giving up my lease was part of a > chain > of events that guaranteed the next guy he *could* open the file > immediately, > and the open succeeded immediately when I gave up my lease, then I might > simply give up the lease and then blocking-reacquire it. That minimizes > the > time I *don't* have my lease, while supposedly not getting in anyone's > way. > > And so: > > > If the lease breaker's blocked open() or truncate() is > > interrupted by a signal handler, then the system call > > fails with the error EINTR, but the other steps still > > occur as described above. If the lease breaker is > > killed by a signal while blocked in open() or trun- > > cate(), then the other steps still occur as described > > above. If the lease breaker specifies the O_NONBLOCK > > flag when calling open(), then the call immediately > > fails with the error EWOULDBLOCK, but the other steps > > still occur as described above. > > In this paragraph, which generally I find good, you might want to caution > that although the steps still occur with O_NONBLOCK, you introduce a race > condition and are not guaranteed to ever successfully open the file > unless you open it in blocking mode. So I might do this: > > - open(O_NONBLOCK) -> EWOULDBLOCK > - (no special time delay) > - open(^O_NONBLOCK) -> success within a short time But the above steps gain nothing over simply doing: - open(^O_NONBLOCK) -> success within a short time > > And that leads me to explain my final point about the security problem, > which doesn't seem to have an obvious workaround if you use the above > method: > > - open(O_NONBLOCK) -> EWOULDBLOCK > - someone replaces the leased file with a fifo > - open(^O_NONBLOCK) -> blocks forever > > My totally nonblocking daemon may be forced to block in order to acquire > a lease, but the blocking period has a guaranteed maximum, so it's not so > bad. > However, the file might suddenly become a fifo, which has no guaranteed > maximum timeout, and that's bad. > > At this point the workarounds are getting slightly crazy, but it looks > like > a fork()-and-open()-with-timeout mechanism might be the only safe way to > go. > > Not sure if you care to document anything to this extent, but my point is > that you might caution about O_NONBLOCK and leases; basically it's not > very useful because there's no guarantee it'll ever work. The thing is, the more general issue you are talking about here is race conditions of a type which can apply in any number of places when writing system programs. There is no compelling reason to document especially this one. There is also a second reason I'm inclined not to add more text. File leases are poorly specified -- it is hard to get information about what they *should* be doing. And it seems that really they are only intended for use with the SMB/CIFS protcols. Cheers, Michael -- Michael Kerrisk maintainer of Linux man pages Sections 2, 3, 4, 5, and 7 Want to help with man page maintenance? Grab the latest tarball at ftp://ftp.win.tue.nl/pub/linux-local/manpages/ and grep the source files for 'FIXME'. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]