> 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]

Reply via email to