Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 01 Nov 2003 13:39:15 -0800
From:      Terry Lambert <tlambert2@mindspring.com>
To:        andi payn <andi_payn@speedymail.org>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: O_NOACCESS?
Message-ID:  <3FA42803.BA6EDF62@mindspring.com>
References:  <1067528798.36829.2128.camel@verdammt.falcotronic.net> <1067627608.825.56.camel@verdammt.falcotronic.net>

next in thread | previous in thread | raw e-mail | index | archive | help
andi payn wrote:
> Now hold on. The standard (by which I you mean POSIX? or one of the UNIX
> standards?) doesn't say that you can't have an additional flag called
> O_NOACCESS with whatever value and meaning you want.

A strictly conforming implementation can not expose things into
the namespace that are not defined by the standard to be in the
namespace, when a manifest constant specifying a conformance level
is in scope.

This is the main reason for things like _types.h.


> Obviously, code that relies on such a flag will be non-portable, since
> no standard defines such a flag, but that's fine, since the intended
> uses (writing a FreeBSD-specific backend for fam, for example) aren't
> expected to be portable anyway.

Not just"not portable", but "fails to conform to standards".


> If O_NOACCESS happens to be == O_ACCMODE on FreeBSD--just as it is on
> linux--and if that happens to also be == O_WRONLY | O_RDWR (with no
> other flags set), I don't see how that changes anything.

Other than the security issues it raises, you mean, right?


[ ... ]
> > 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.
> 
> First, again, this is intended to be used for non-portable code, and
> therefore, the fact that this happens not to be true on FreeBSD means
> it's irrelevant that it could be true elsewhere. Especially since, if
> O_NOACCESS were added to FreeBSD, it would still fail to exist entirely
> on other platforms, which means it matters little what value it might
> have if it did exist--code written to use O_NOACCESS won't compile on
> platforms without O_NOACCESS.

You nead to look at the implementation of VOP_OPEN in FreeBSD;
specifically, you need to look at the fact that fp->f_flags is
passed as one of its parameters, and that the FS is permitted
to interpret these flags in an FS-dependent fashion.

Then you need to at the fact that FreeBSD supports locadable FS
types, and that there are third party FS's that proxy operations
over the network, which can include a network version of the
flags, and conversion back and forth could therefore end up
being ambiguous.

Really, it needs to be a bitmap internally in FreeBSD, as well,
but that's a big step.


> Second, any platform that defines O_NOACCESS could do so differently. On
> FreeBSD, as on linux, the most sensible definition is O_NOACCESS ==
> O_WRONLY | O_RDWR == 3. Or a platform that defined O_RDONLY as 1 and
> O_WRONLY as 2, the most sensible definition would be O_NOACCESS == 0.

I pray this flag never gets adopted outside of Linux...


> > In fact, externally, they are bits, but internally, in the kernel,
> > they are manifest constants.
> 
> Yes, FFLAGS and OFLAGS convert between the two. If you look at how this
> works in the linux kernel, you'll see that O_RDONLY (0) converts to
> FREAD (1); O_WRONLY (1) to FWRITE (2); O_RDWR (2) to FREAD | FWRITE (3);
> and O_NOACCESS (3) to 0. This could be done the same way in FreeBSD.*
> 
> * Actually, this is a tiny lie; linux has a 2-bit internal access flags
> value which it derives in this way, and uses the original passed-in
> flags for everything except access. FreeBSD instead just adds 1, relying
> on the fact that the lower 2 bits will never be 3, and therefore all of
> the other bits will stay the same. This means that enabling this value
> would make the FFLAGS and OFLAGS macros slightly more complicated on
> FreeBSD.

It would be more useful to intern them as a bitmap, IMO, and get rid
of the conversion.  The problm is compatability with historical
source code passing literal constants instead of manifest values.


> > The most useful thing you could do with this, IMO, is opn a directory
> > for fchdir().
> 
> Except that you can already do exactly this with chdir(). But I can see
> that you might at some point want to check the directory before
> chdir'ing to it, or pass an fd down into some function instead of a
> string, and this would be useful in such a case.

Or deal with issues of privilege granted merely by open.  For
example, on FreeBSD, an implementation of this would permit any
normal user to do INB/OUTB to any I/O port on any hardare on the
machine.

This is a can of worms.


> > 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...
> 
> How would it allow that? If you can open files outside your chroot
> environment--even files you would otherwise have read access to--it's
> not much of a chroot!

Mounted procfs within a chrooted environment.  Admittedly, FreeBSD
is moving away from procfs, but on Linux, it's a serious issue,
since such basic utilities as "ps" and so on won't work without it.


> > > 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.
> 
> Actually, you'd be surprised at how much has been explicitly added to
> the kernel (and, more, to the filesystem code, especially reiser) for
> lilo's benefit.

I wouldn't.  I think it's "too much", and I'd hate to drag the same
cruft into FreeBSD for the same reasons.

One option for you would be to make this a kernel module... then it
could be of use to the people who need it, while not bothering the
rest of the world.  Sort of like FreeBSD installing ports with
restricted privileges by default, and requiring that you do some
small amount of reconfiguration to get additional features in them
at a reduced security level.

-- Terry



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3FA42803.BA6EDF62>