Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000141 [1003.1(2008)/Issue 7] System Interfaces Objection Omission 2009-09-02 15:42 2013-04-16 13:06
Reporter eblake View Status public  
Assigned To ajosey
Priority normal Resolution Accepted As Marked  
Status Closed  
Name Eric Blake
Organization N/A
User Reference ebb.O_NONBLOCK
Section open
Page Number 1380
Line Number 45239
Interp Status Approved
Final Accepted Text Note: 0000232
Summary 0000141: O_NONBLOCK flag to open
Description The current specification of the O_NONBLOCK flag to open and openat has some holes.

Older versions of the Linux kernel lacked (or silently ignored) O_DIRECTORY. Therefore, it is common to see code similar to:

#ifndef O_DIRECTORY
# define O_DIRECTORY 0
#endif
#ifndef O_CLOEXEC
# define O_CLOEXEC 0
#endif
int fd = open (name,
               O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
if (!O_DIRECTORY && 0 <= fd)
  {
    /* Prove that fd is indeed a directory. */
    struct stat st;
    if (fstat (fd, &st) == -1 || !S_ISDIR (st.st_mode))
      {
        close (fd);
        errno = ENOTDIR;
        fd = -1;
      }
  }

The idea is that if the user can't atomically guarantee that a directory will be opened, at least they can guarantee that they won't change a controlling terminal or block on a FIFO, and can use followup checks to simulate O_DIRECTORY with minimal semantic difference. For an example of this, which goes one step further in also using O_NOFOLLOW to avoid symlink-to-directory, see http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/chdir-safer.c [^]

From the POSIX perspective, the use of O_NOCTTY is safe albeit redundant - files that name directories (either a directory, or a symlink-to-directory) are mutually exclusive from terminal devices, so if name describes a directory, O_NOCTTY is silently ignored (line 45222) and open succeeds; if name is a terminal device, then O_DIRECTORY causes failure (line 45209), so the controlling terminal cannot change. And for the older non-POSIX kernels, the user has added a safety valve to prevent changing the controlling terminal until they can verify that the intent of opening a directory was met.

But for O_NONBLOCK, there is a problem. For the non-POSIX case, the user has tried to add a safety valve that if name is a FIFO rather than a directory, the application will not block (avoiding a delay or even deadlock at reaching the subsequent fstat to reject the non-directory). However, according to POSIX, the use of O_NONBLOCK is unspecified on a directory, so it is conceivable that an implementation could choose to use the unspecified behavior umbrella by making open fail if name does not support non-blocking mode, rendering the combination O_DIRECTORY|O_NONBLOCK useless for a strictly compliant application (it would either fail because a non-directory was specified, or because a directory does not support non-blocking mode). Thankfully, there are no known existing implementations of open that fail if O_NONBLOCK is specified on a file that does not support non-blocking mode, although it is not clear whether a subsequent fcntl(F_GETFL) will see O_NONBLOCK.

Furthermore, fcntl has no restrictions on using F_SETFL to enable O_NONBLOCK for any type of file descriptor. So, while it is currently unspecified what happens when using O_NONBLOCK to open a directory or a regular file, there appears to be no restriction on setting it later.

Even if a user tries to avoid unspecified behavior associated with O_NONBLOCK by only using open(O_NONBLOCK) if they have previously stat()ed name and seen that it is a FIFO, there is an inherent data race where name can be changed to a non-FIFO between the stat() and the open(); thus it is impossible to for open(O_NONBLOCK) to ensure that it is avoiding unspecified behavior, based on the current specification.

It would be nicer if the specification of O_NONBLOCK were tightened such that it is well-defined as never causing an error, similar to O_NOCTTY or O_TTY_INIT, while still leaving implementations the flexibility of ignoring the flag on file descriptors where non-blocking is not supported. That way, O_NONBLOCK can safely be used with O_DIRECTORY, and applications need not worry about triggering unspecified behavior due to a race between stat() and open().
Desired Action At line 26904 (fcntl F_GETFL), add a sentence:

If filedes does not support non-blocking operations, it is unspecified whether the O_NONBLOCK flag will be ignored.

At line 45239 (open O_NONBLOCK), change:

Otherwise, the behavior of O_NONBLOCK is unspecified.

to:

Otherwise, the O_NONBLOCK flag shall not cause an error, but it is unspecified whether the file status flags will include the O_NONBLOCK flag.
Tags tc1-2008
Attached Files

- Relationships
related to 0000658Appliedajosey Undefined/unspecified behavior clauses in description of open have race conditions 

-  Notes
(0000213)
geoffclare (manager)
2009-09-03 10:09

A small change to the code would avoid the unspecified behaviour
in the standard:

oflags = O_RDONLY;
#ifdef O_DIRECTORY
oflags |= O_DIRECTORY;
#else
oflags |= O_NONBLOCK | O_NOCTTY;
#endif
#ifdef O_CLOEXEC
oflags |= O_CLOEXEC;
#endif
int fd = open (name, oflags);
#ifndef O_DIRECTORY
if (0 <= fd)
{
    /* Prove that fd is indeed a directory. */
    ...
}
#endif

Since the standard requires O_DIRECTORY to be defined, with this code
O_NONBLOCK will only be used on a directory on non-conforming systems
(including systems that conform to older revisions of POSIX, but a
change to the current standard would not affect them).

Nevertheless, I believe there is a case for changing the standard
here. The reason is that when an application calls open() on an
existing file, it cannot be certain what file type the file will have
at the time of the open. (The best it can do is stat() the file
beforehand, but as Eric points out this would create a race condition
whereby the file could change between the stat() and the open().)
Thus an application that is expecting to open a FIFO, and calls open()
with O_NONBLOCK set, could end up opening a regular file or a
directory instead, and has no way of preventing this from happening.
The standard should specify the behaviour sufficiently for
applications to be able to detect this situation.
(0000216)
eblake (manager)
2009-09-03 22:37

The proposed text has a typo; the sentence to be added to fcntl belongs at line 26910 F_SETFL (not 26904 F_GETFL).
(0000232)
nick (manager)
2009-09-17 15:52
edited on: 2009-11-07 07:34

Interpretation response
------------------------

The standard does not speak to this issue, and as such
no conformance distinction can be made between alternative
implementations based on this. This is being referred to the
sponsor

Rationale:
-------------
None.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------

Make the change

At page 807 line 26910 (fcntl F_SETFL), add a sentence:

If fildes does not support non-blocking operations, it is unspecified whether the O_NONBLOCK flag will be ignored.

At line 45239 (open O_NONBLOCK), change:

Otherwise, the behavior of O_NONBLOCK is unspecified.

to:

Otherwise, the O_NONBLOCK flag shall not cause an error, but it is unspecified whether the file status flags will include the O_NONBLOCK flag.


- Issue History
Date Modified Username Field Change
2009-09-02 15:42 eblake New Issue
2009-09-02 15:42 eblake Status New => Under Review
2009-09-02 15:42 eblake Assigned To => ajosey
2009-09-02 15:42 eblake Name => Eric Blake
2009-09-02 15:42 eblake Organization => N/A
2009-09-02 15:42 eblake User Reference => ebb.O_NONBLOCK
2009-09-02 15:42 eblake Section => open
2009-09-02 15:42 eblake Page Number => 1380
2009-09-02 15:42 eblake Line Number => 45239
2009-09-03 10:09 geoffclare Note Added: 0000213
2009-09-03 22:37 eblake Note Added: 0000216
2009-09-17 15:52 nick Note Added: 0000232
2009-09-17 15:54 nick Interp Status => ---
2009-09-17 15:54 nick Status Under Review => Interpretation Required
2009-09-17 15:54 nick Resolution Open => Accepted As Marked
2009-09-17 15:55 nick Note Edited: 0000232
2009-09-17 15:55 nick Final Accepted Text => Bugnote: 232
2009-09-17 15:56 nick Interp Status --- => Pending
2009-09-17 15:56 nick Final Accepted Text Bugnote: 232 => Note: 0000232
2009-09-17 15:56 nick Note Edited: 0000232
2009-09-17 16:00 ajosey Note Edited: 0000232
2009-11-07 07:34 ajosey Note Edited: 0000232
2009-11-07 07:34 ajosey Interp Status Pending => Proposed
2009-12-07 16:56 ajosey Interp Status Proposed => Approved
2010-09-21 11:13 geoffclare Tag Attached: tc1-2008
2011-11-15 01:56 binki Issue Monitored: binki
2013-02-14 16:46 eblake Relationship added related to 0000658
2013-04-16 13:06 ajosey Status Interpretation Required => Closed


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker