Debian Bug report logs - #339037
open(2) man page doesn't document potential EWOULDBLOCK return code

version graph

Package: manpages-dev; Maintainer for manpages-dev is Martin Schulze <joey@debian.org>; Source for manpages-dev is src:manpages.

Reported by: Avery Pennarun <apenwarr@nit.ca>

Date: Mon, 14 Nov 2005 17:03:02 UTC

Severity: normal

Tags: fixed-upstream

Found in version manpages-dev/1.60-2

Fixed in version manpages/2.14-1

Done: Martin Schulze <joey@infodrom.org>

Bug is archived. No further changes may be made.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#339037; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Avery Pennarun <apenwarr@nit.ca>:
New Bug report received and forwarded. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: Avery Pennarun <apenwarr@nit.ca>
To: submit@bugs.debian.org
Subject: open(2) man page doesn't document potential EWOULDBLOCK return code
Date: Mon, 14 Nov 2005 11:56:32 -0500
Package: manpages-dev
Version: 1.60-2

We've just been bitten by this at work.

If you read the LEASES section of fcntl(2), it explains that open() with
O_NONBLOCK could cause open to return EWOULDBLOCK.  This is not explained
anywhere on the open() page; open() has many possible return codes, none of
which are EWOULDBLOCK.  (There is a comment about opening fifos in
nonblocking mode, but the error code description implies that this would
return ENXIO, not EWOULDBLOCK.)

Also, the fcntl(2) page doesn't say whether opening a leased file with
O_NONBLOCK will actually request the lease to be broken or not.  It appears
you *have* to open in blocking mode in order to open a leased file at all,
but that's not clear from the description.

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.

Have fun,

Avery



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#339037; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to "Michael Kerrisk" <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #10 received at 339037@bugs.debian.org (full text, mbox):

From: "Michael Kerrisk" <mtk-manpages@gmx.net>
To: Avery Pennarun <apenwarr@nit.ca>,339037@bugs.debian.org
Cc: control@bugs.debian.org
Subject: Re: Bug#339037: open(2) man page doesn't document potential EWOULDBLOCK return code
Date: Thu, 17 Nov 2005 15:59:58 +0100 (MET)
tags 339037 fixed-upstream
thanks

Hello Avery,

> If you read the LEASES section of fcntl(2), it explains that open() with
> O_NONBLOCK could cause open to return EWOULDBLOCK.  This is not explained
> anywhere on the open() page; open() has many possible return codes, none
> of which are EWOULDBLOCK.  (There is a comment about opening fifos in
> nonblocking mode, but the error code description implies that this would
> return ENXIO, not EWOULDBLOCK.)

Thanks.  In open.2, I have added the following text:

       EWOULDBLOCK
              The O_NONBLOCK flag was specified, and an incom-
              patible   lease   was  held  on  the  file  (see
              fcntl(2)).

> Also, the fcntl(2) page doesn't say whether opening a leased file with
> O_NONBLOCK will actually request the lease to be broken or not.  

It explains a sequence of steps, which include the lease being
broken.  Those steps occur independently of O_NONBLOCK.  The
man page does pretty much imply that IMO.  But I do agree that
things could be stated a little more verbosely.

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

In fcntl.2, I removed the phrase that you referred to that
specified O_NONBLOCK.  Later in the description, I added
this new text:

       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.

These changes will appear in man-pages-2.14.

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'.



Tags added: fixed-upstream Request was from "Michael Kerrisk" <mtk-manpages@gmx.net> to control@bugs.debian.org. Full text and rfc822 format available.

Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#339037; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Avery Pennarun <apenwarr@nit.ca>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #17 received at 339037@bugs.debian.org (full text, mbox):

From: Avery Pennarun <apenwarr@nit.ca>
To: 339037@bugs.debian.org
Subject: Re: Bug#339037: open(2) man page doesn't document potentia
Date: 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.  So the first
claim above, that you *have* to open in blocking mode, is not strictly true. 
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.)

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

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.

Have fun,

Avery



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#339037; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to "Michael Kerrisk" <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #22 received at 339037@bugs.debian.org (full text, mbox):

From: "Michael Kerrisk" <mtk-manpages@gmx.net>
To: Avery Pennarun <apenwarr@nit.ca>
Cc: 339037@bugs.debian.org
Subject: Re: Bug#339037: open(2) man page doesn't document potentia
Date: Wed, 23 Nov 2005 10:58:03 +0100 (MET)
> Von: Avery Pennarun <apenwarr>
> An: 339037@bugs.debian.org
> 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'.



Reply sent to Martin Schulze <joey@infodrom.org>:
You have taken responsibility. Full text and rfc822 format available.

Notification sent to Avery Pennarun <apenwarr@nit.ca>:
Bug acknowledged by developer. Full text and rfc822 format available.

Message #27 received at 339037-close@bugs.debian.org (full text, mbox):

From: Martin Schulze <joey@infodrom.org>
To: 339037-close@bugs.debian.org
Subject: Bug#339037: fixed in manpages 2.14-1
Date: Sun, 11 Dec 2005 07:47:14 -0800
Source: manpages
Source-Version: 2.14-1

We believe that the bug you reported is fixed in the latest version of
manpages, which is due to be installed in the Debian FTP archive:

manpages-dev_2.14-1_all.deb
  to pool/main/m/manpages/manpages-dev_2.14-1_all.deb
manpages_2.14-1.diff.gz
  to pool/main/m/manpages/manpages_2.14-1.diff.gz
manpages_2.14-1.dsc
  to pool/main/m/manpages/manpages_2.14-1.dsc
manpages_2.14-1_all.deb
  to pool/main/m/manpages/manpages_2.14-1_all.deb
manpages_2.14.orig.tar.gz
  to pool/main/m/manpages/manpages_2.14.orig.tar.gz



A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 339037@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Martin Schulze <joey@infodrom.org> (supplier of updated manpages package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.7
Date: Sun, 11 Dec 2005 15:41:22 +0100
Source: manpages
Binary: manpages manpages-dev
Architecture: source all
Version: 2.14-1
Distribution: unstable
Urgency: low
Maintainer: Martin Schulze <joey@debian.org>
Changed-By: Martin Schulze <joey@infodrom.org>
Description: 
 manpages   - Manual pages about using a GNU/Linux system
 manpages-dev - Manual pages about using GNU/Linux for development
Closes: 336875 339037 339037
Changes: 
 manpages (2.14-1) unstable; urgency=low
 .
   * New upstream release, with the following changes
     - New rexec(3) (Closes: Bug#336875)
     - Clarified file leases in fcntl(2) (Closes: Bug#339037)
     - Completed errors section in open(2) (Closes: Bug#339037)
Files: 
 3eec346638bba39f0d93d1114239d3c5 584 doc - manpages_2.14-1.dsc
 dddd6cb167c71096b0a8164191f0fa22 1065989 doc - manpages_2.14.orig.tar.gz
 600eb16e8b6f51db4fc7c801a306f068 47285 doc - manpages_2.14-1.diff.gz
 ffb4681f1fd8dbd5d5cae40320a8adc6 406402 doc important manpages_2.14-1_all.deb
 a7b32f93d360c41f706c3fd9c5190a36 1109608 doc standard manpages-dev_2.14-1_all.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFDnEbDW5ql+IAeqTIRAlT1AKCWuSmHU4LOlSHzh+u3E3UrTm0KZQCfVLTr
JQeF4sFsPwgn1/9qSwmIa5Q=
=I5zY
-----END PGP SIGNATURE-----




Bug archived. Request was from Debbugs Internal Request <owner@bugs.debian.org> to internal_control@bugs.debian.org. (Mon, 25 Jun 2007 06:13:11 GMT) Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Mon Apr 21 09:48:59 2014; Machine Name: buxtehude.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.