Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Oct 2002 11:02:52 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Robert Watson <rwatson@FreeBSD.ORG>
Cc:        Maxim Sobolev <sobomax@FreeBSD.ORG>, "Danny J. Zerkel" <dzerkel@columbus.rr.com>, "Vladimir B. Grebenschikov,Moscow,408-7227,123-4567,Some-info" <vova@express.ru>, freebsd-arch@FreeBSD.ORG, freebsd-current@FreeBSD.ORG
Subject:   Re: short uid/gid
Message-ID:  <3DADA9CC.CBF9E1E6@mindspring.com>
References:  <Pine.NEB.3.96L.1021016125106.24763B-100000@fledge.watson.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Robert Watson wrote:
> On Wed, 16 Oct 2002, Terry Lambert wrote:
> > Robert Watson wrote:
> > > I'm not convinced there's any value to providing the backward
> > > compatibility that has to be asked for: the only benefit to the current
> > > short-based API is that it allow serious security holes while not
> > > following the standard API offered by other platforms (except Linux).
> >
> > The main benefit, to my mind, is standards compliance.  The secondary
> > benefit is ABI similarity for the purposes of supporting ABIs to run
> > non-native software (e.g. Linux prior to 2.4).
> 
> Could you point me at the standard that indicates these fields should be
> shorts?  We're all advocating switching to uid_t/gid_t/id_t here, the only
> question is with regard to compatibility.  Platforms such as Solaris
> already use uid_t/gid_t for these fields, and we break portable
> applications because applications assume that uid_t fits into ipc_perm.uid
> (for example).

The field sizes have, unfortunately, been documented in manual
pages on a lot of platforms.  Rather than survey them all, we
can look at the FreeBSD manual page for shmctl(), which has an
overflow on shm_nattch, as well as shm_atime/shm_dtime/shm_ctime;
by extension, it also includes an struct ipc_perm as its first
element (rather than a pointer to an ipc_perm struct with a
version number field), which has ushort cuid/cgid/uid/gid/mode/seq
members.

If we look at the shmctl() definition in the X/Open and POSIX
documentation, we see that shm_perm.mode's significance is
limited to "low-order nine bits".

In semctl(), the same standard defined the arg.array pointer as
pointing to an array of unsigned shorts.

Similarly, the standard references struct ipc_perm in the sys/sem.h
entry point.

There is actually arguabley non-opaque data which has been exported
by proxy, which should not have been exported at all; specifically,
the only members defined to be exported by the standards in the
ipc_perm are: uid/gid (owner), cuid/cgid (creator), and mode.

The upshot is that the standards failed to make the size of the
values in conforming implementations required to be opaque, and now
we have data interfaces we have to live with for source code
compatability reasons, whose definitions are not controlled by a
standard.  8-(.


> > Binary backward compatability *demands* that you limit the range of your
> > UIDs and GIDs to what will fit in a uint16_t, just as the recent issue
> > with a pid_t exceeeding this size has damaged binary backward
> > compatability with third party a.out binaries.
> 
> This has to do with the size of the field.  uid_t and gid_t are 32-bit on
> most relevant platforms, although there are lingering software
> compatibility issues (such as the Sysem V IPC issue).  The goal now is to
> correct lingering incompatibilities so that we can properly support these
> ranges.

Julian recently exposted a binary compatability issue when PIDs
exceeded a short.  See the -current archives for details.

There's a similar problem at work here, except that now it's a
security issue, I think.


> > Truncating of oversized values for credentials is Bad(tm), in that what
> > you get is a different credential.  The constraint has to be a priori
> > enforced, or it's meaningless.
> 
> I think we're in agreement here.  Unfortunately, because of the "short"
> uid/gid/cuid/cgid fields, truncation is *already* happening.  That's what
> we're trying to fix.  If you try to crush a uid_t into ipc_perm.uid on
> FreeBSD, the field is truncated, resulting in a vulnerability.

This will happen automatically on any FreeBSD system where you are
running an old binary.  The crushing occurs in kernel space, not in
user space.  That's the issue that the Linux IPC_64 author stated
that they were addressing.  By doing it the way they did, the
guaranteed that, so long as the kernel has a consistent view, then
user space would have a consistent view.


> What pushing the type checking into the application space does is
> generate warnings for applications making bogus assumptions, and
> corrects the truncation performed by the kernel in the current
> scenario.

It only generates warnings on new compilations, not for already
compiled legacy applications, which must continue to function
without modification.


> I.e., when a SysVIPC shm segment is created by a user with a uid
> that doesn't fit in short, the kernel gets it "wrong".  The change
> we're talking about will fix the kernel, and make type problems
> visible to the applications if they make incorrect assumptions.  Of
> course, past applications assuming 16-bit uids and gids will still
> be wrong, nothing changes that, but we do fix current applications.

As the Linux approach demonstrates, it's possible to get the new
applications right, without inherently making the old applications
"wrong".  I would not advise decorating symbols for this, though.
Using the approach of a different cmd space is the correct approach,
and can be done without symbol decoration.

In fact, I used exactly this approach, when I defined the F_RGETLK,
F_RSETLK, and F_RSETLKW commands in fcntl(), for support of NFS
locking, back in 1996/1997.  By using a seperate command space, you
allow use of structures special to that command space.

Unless you want to go into adaptive symbol decoration, like Linux
does (which would be very hard for FreeBSD to follow), the user
space conversion to the expected kernel ABI will not work... in
particular, FreeBSD already mixes support for 16 vs. 32 bit values
for these fields across kernel interfaces, which is Wrong(tm).  At
the place one was converted, *all* should have been converted, and
the ABI versioned, and this didn't happen.  We are already screwed,
and the question is what's going to be done about it.

Unlike me as this is, my suggestion would be to wait until later,
and fix everything at once, so that at least there was internal and
external consistency in place.  By everything, I include *everything*,
including the on-disk quota structure members, which also have shorts
for certain fields, and have a binary forward compatability conversion
problem facing them.

From the Linux ABI argument, which was the first argument put forward,
the actual fix is to update the Linux port to provide the Linux 2.4
glibc_2_2 decorations as well as the glibc_2_0 decorations, and to
support whatever interface it is that the Linux library is using to
determine if the kernel supports the new or the old interface.  That
will fix the problem that originated the current discussion.

In a lot of ways, the Linux approach is superior, although their
maintaining the old interfaces in the newer version of the glibc
is actually a bad thing: this is the same problem that Novell had
wth it's API's, and I rather expect that Linux will see the same
result: everyone will code for the older API's, since it will give
them the largest possible potential user base.  However, the beauty
of the Linux approach is that they can rev. the ABI in the kernel
to support only a single paradigm, and the conversion is handled in
user space at the library level.

For FreeBSD, the moral equivalent would be the ability to build an
older version of a shared library, with the ability to use a newer
version of the host ABI.  FreeBSD doesn't really support that, at
this point, unfortunately, because FreeBSD still supports static
binaries, and static binaries imply a static ABI support that must
be carried forward.

> > His approach avoids the proliferation of system call entry points, which
> > may conflict with those of other BSDs (among other things).  BSDI
> > limited the number of available additional FreeBSD system calls in a
> > standardization effort a while back, if you'll remember, so a
> > proliferation of calls is Bad.  In addition, the compatability required
> > this proliferation going forward.
> 
> I suspect that this may end up being a red herring.  You do realize that
> OpenBSD and NetBSD have *already* made precisely the change I am
> describing?  Here's the exerpt from OpenBSD's ipc.h:

Yes, I understand that they have made this change.  I'm not really
objecting to changing ipc_perm.


> We're *improve* our compatibility with other BSD platforms by making these
> changes.

With respect, this will only become relevent when we rely on
OpenBSD or NetBSD ABI support for access to applications.

As to the general argument of "we should share code where
possible", one could argue that we should start with the VFS
interfaces, since NetBSD has working VFS stacking.  There are
a lot of other interfaces in this category, e.g. NetBSD's
support for running ABI's from a much larger number of foreign
platforms for a CPU architecture, and the fact that the FreeBSD
and NetBSD and OpenBSD SYN cache code are not totally congruent.
The FreeBSD and NetBSD "cookie" interface for restart of directory
traversals are similarly inverted.  There are millions of examples
of gratuitous differences that could be corrected -- and should be,
before trying to make this argument.


> > FWIW, I would agree with you, if you were advocating a cross-OS ABI
> > definition of manifest constants, so that FreeBSD's new ABI, and, say,
> > Solaris or Linux's ABI, were more congruent (you could get this without
> > a new sstem call vector entry point, by using a different "ELF brand"
> > value), but that's not what you are advocating.
> 
> I'm advocating we adopt pretty much the ABI for these calls that Solaris
> uses.  If you inspect their ipc.h, you'll see that they define two
> versions of the structure, ipc_perm, and ipc_perm32.  ipc_perm is the
> version that makes use of types such as uid_t and gid_t; ipc_perm32
> hard-codes these fields to 32-bit and can be used for compatibility.

No, actually you are suggesting adopting the API, with a similar
looking, but inequal ABI.  That's very different than the point I
was trying to make here.

If you are going to follow, rather than lead, then you would be best
served to follow the system with the largest software based that is
most similar to your own trarget market, in hopes of being able to
capture converts on the basis of binary compatability with the least
amount of pain.

Right now, in order to run Solaris binaries, FreeBSD requires a lot
of hacking, including the installation of commerciall licensed
shared libraries.


> > Also FWIW, my personal preference would be to follow the Solaris ABI;
> > it's the least volatile of all ABI's in this area.  In terms of the
> > available applications, Linux is probably a better choice, but in terms
> > of the amount of maintenance work required, Solaris is far and away the
> > leader.
> 
> We already have the SysVIPC wrappers for the Linux code, but those are
> actually broken because they don't take into account our truncation bugs.

ABI, not API.

And out "truncation bugs" are a result of a partial conversion of
the APIs.  If you are suggesting a complete conversion, well, I will
again point out that doing this job correctly touches a hell of a
lot more code than we should be looking at touching, just prior to
a major (not even a point!) release (starting with the on disk
quota structures, etc.).

-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




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