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>