O_NOACCESS?

Terry Lambert tlambert2 at mindspring.com
Fri Oct 31 01:21:06 PST 2003


andi payn wrote:
> As far as I can tell, FreeBSD doesn't have anything equivalent to
> linux's O_NOACCESS (which is not in any of the standard headers, but
> it's equal to O_WRONLY | O_RDWR, or O_ACCMODE). In linux, this can be
> used to say, "give me an fd for this file, but don't try to open it for
> reading or writing or anything else."

The standard does not permit this.

First off, O_ACCMODE is a bitmask, and is guaranteed to be
inclusive of the bits for O_RDONLY, O_WRONLY, and O_RDWR, but
*not* guaranteed to not be inclusive of additional bits,
reserved or locally defined but outside the _POSIX_SOURCE
namespace.  By using this value as a parameter, you could very
well be setting many more bits, and you could be setting bits
for local implementation options that you really, really do
not want to set.

Second, the standard is ambiguous as to how O_RDWR is defined;
it is perfectly permissable to define these values as:

#define O_RDONLY	1			/* the read bit */
#define O_WRONLY	2			/* the write bit */
#define O_RDWR		(O_RDONLY|O_WRONLY)	/* read + write */

In which case, your example is (O_RDWR|O_WRONLY) == O_RDWR.  The
standard does not indicate whether the implementation is to use
bits, or sequential manifest constants, only that the bits that
make up the constants be in the range covered by O_ACCMODE.

In fact, externally, they are bits, but internally, in the kernel,
they are manifest constants.


> This allows you to get an fd to pass to fcntl (e.g., for dnotify), or
> call ioctl's on, etc.--even if you don't have either read or write
> access to the file. The obvious question is, "Why should this ever be
> allowed?" Well, if you can stat the file, why can't you, e.g., ask
> kevent to monitor it?

The most useful thing you could do with this, IMO, is opn a directory
for fchdir().  Of course, allowing this on directories for which you
are normally denied read/write permissions would be a neat way to
escape from chroot'ed environments and compromise a host system...


> In FreeBSD, this doesn't work; you just get EINVAL.
> 
> Having O_NOACCESS would be useful for the fam port, for porting pieces
> of lilo, and probably for other things I haven't thought of yet. (I
> believe that either this was added to linux to support lilo, or the open
> syscall just happened to work this way, and once the lilo developers
> discovered this and took advantage of it, it's been retained that way
> ever since to keep lilo working.)

The latter is most likely.  In any case, this would not be allowed
by GEOM for the purpose to which LILO is trying to put it, unless
you were to modify GEOM to add a control path for parents of
already opened devices.  If you did this, you might as well just
add a proper set of abstract fcntl's to GEOM, and get rid of all
the raw disk crap in user space, and unbreak dislabel and the other
stuff that GEOM broke when it went in.


> On the other hand, BSD has done without it for many years, and there's
> probably a good reason it's never been added. So, what is that good
> reason?

fcntl.h:
#define FFLAGS(oflags)  ((oflags) + 1)


> I don't think there's a backwards-compatibility issue.

Unfortunately, yes, there is.  The values are not bits, internally
to the kernel.  The conversion to internal form merely adds 1, it
doesn't shift the values.


-- Terry


More information about the freebsd-hackers mailing list