From owner-freebsd-hackers@FreeBSD.ORG Sat Nov 1 16:28:30 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3418416A4CE for ; Sat, 1 Nov 2003 16:28:30 -0800 (PST) Received: from mta10.adelphia.net (mta10.adelphia.net [68.168.78.202]) by mx1.FreeBSD.org (Postfix) with ESMTP id C23B443F93 for ; Sat, 1 Nov 2003 16:28:28 -0800 (PST) (envelope-from andi_payn@speedymail.org) Received: from [10.1.0.9] ([68.65.235.109]) by mta13.adelphia.net (InterMail vM.5.01.06.05 201-253-122-130-105-20030824) with ESMTP id <20031102002111.CWIE20181.mta13.adelphia.net@[10.1.0.9]>; Sat, 1 Nov 2003 19:21:11 -0500 From: andi payn To: Terry Lambert In-Reply-To: <3FA42803.BA6EDF62@mindspring.com> References: <1067528798.36829.2128.camel@verdammt.falcotronic.net> <3FA22930.C6EC97A9@mindspring.com> <1067627608.825.56.camel@verdammt.falcotronic.net> <3FA42803.BA6EDF62@mindspring.com> Content-Type: text/plain Message-Id: <1067732469.825.487.camel@verdammt.falcotronic.net> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.4.5 Date: Sat, 01 Nov 2003 16:21:10 -0800 Content-Transfer-Encoding: 7bit cc: freebsd-hackers@freebsd.org Subject: Re: O_NOACCESS? X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Nov 2003 00:28:30 -0000 On Sat, 2003-11-01 at 13:39, Terry Lambert wrote: > andi payn wrote: > > Now hold on. The standard (by which I you mean POSIX? or one of the UNIX [...] > 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. Yes. As I mentioned at the beginning, you don't get O_NOACCESS in linux by pulling in the standard headers, and I wasn't suggesting anything different. [...] > Not just"not portable", but "fails to conform to standards". Note that the Single UNIX Specification says that open _may_ fail with EINVAL if the value of the oflag argument does not contain exactly one of the three access modes. So, if you've written code (for some reason) that expects that it _must_ fail in such a situation, that's non-comforming code. > > 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? Are you saying that having O_NOACCESS == O_ACCMODE raises security issues beyond any raised by having O_NOACCESS at all? Or is it the fact that it would the same value as in linux, so linux code (whether recompiled for FreeBSD or run under ABI compatibility) that expected to be able to open a file without getting read or write access would be able to do so? Again, I don't see how this raises security issues beyond whatever may be inherent in O_NOACCESS, if any. Or are you just getting ahead of yourself? > 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. Which version are you looking at? In 5.1, what gets passed if fmode, which is ultimately the result of applying FFLAGS to the original flags passed to open. As for the FS being permitted to interpret these flags in an FS-dependent fashion: I'm pretty sure that a FS that interpreted FREAD to mean write permission, or O_APPEND to mean truncate, would not be considered good. Any FS that assumes that it can read if FREAD is set, and it can write if FWRITE is set, will work correctly when neither is set. And any filesystem that doesn't work this way is already broken. However, there may be some FS's with more subtle issues. For example, an FS might assume that if it doesn't have FWRITE, it must have FREAD. This is (probably) not guaranteed anywhere--but it is currently true, a fact which is logically deducible from the values of the flags, the way FFLAGS works, and the fact that O_ACCMODE returns EINVAL. If this ceases to be true, such an FS might do things wrong. I'd have no problem with providing for each filesystem to specify "I can handle no-access opens," and for any FS that doesn't do so, the kernel would return EINVAL before even talking to the FS (thus preserving current behavior); only if the FS does so could it ever get an fmode with neither FREAD nor FWRITE set. [...] > Really, it needs to be a bitmap internally in FreeBSD, as well, > but that's a big step. By "it needs to be a bitmap internally," you mean that fmode needs to be a bitmap? Well, then, good news: It already is. In fact, I think the equivalent parameter has been a bitmap for every *BSD and going back into AT&T Unix. Currently FFLAGS() is a macro that adds 1. Now, look at the original flags. The low two bits are the O_ACCMODE mask. This part is not a bitmap (O_RDONLY == 0, O_WRONLY == 1, and O_RDWR == 2). But once you add 1, the result is (FREAD == 1, FWRITE == 2, FREAD|FWRITE == 3 == 1|2). The flags value with O_ACCMODE masked out is already a bitmap (not just in FreeBSD; it's even defined to be one in the Single Unix Standard). Adding 1 to flags could only change any of these bits if the two low bits were both 1. But this is not possible, since we've already checked that (flags & O_ACCMODE) != O_ACCMODE. Therefore, fmode is a bitmap. QED. Now, what I'm proposing would allow the low two bits to be 11, which FFLAGS would map to 00 (as it does in linux). While adding 1 does this, it would also affect the higher bits (O_NOACCESS | O_NOBLOCK + 1 is not 0 | O_NOBLOCK, it's 0 | O_APPEND). Therefore, a slightly more complicated FFLAGS is needed if we want fmode to remain a bitmap. (The alternative--the way linux does this--is to pass along both flags and fflags, and using fflags only for the low two bits, which is ugly and messy. I'd much prefer a slightly more complicated FFLAGS.) > > 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... Is this just a non-sequitur, or are you praying that it never gets adopted because it could have different definitions or different systems? In the same way that O_RDONLY can be 0 or 1 on two different platforms, O_NOACCESS could be 3 or 0 on two different platforms. That seems like a good thing, not a bad thing. [...] > 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. You mean by opening /dev/io? There's already a thread about that. The manpage says that "In addition to any file access permissions on /dev/io, the kernel enforces that only the super-user may open this device." Unfortunately, the kernel appears to not enforce any such thing. That's the can of worms. Either the kernel needs to enforce it, or the manpage needs to stop saying that it does. Meanwhile, the manpage says that "even read-only access will grant the full I/O privileges." I'd say that /dev/io should be changed to not allow the privileges if neither FREAD or FWRITE is set (which would require no change to the manpage, or to existing apps, and would open no new security issues)--whichever way the other issue is fixed. > > > 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. So, being able to open a file and then fchdir to it would provide you with... exactly the same exploit that you can already get by chdir'd to it. There's no new security issue here. > > 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. I agree completely. However, I don't think that adding O_NOACCESS is the same thing as dragging in dozens of device-specific and fs-specific ioctl's and two special flags values (if the flags == -1 or -2, it's no longer a bitfield and instead has a special meaning), etc. As opposed to those examples, NOACCESS is a single change, at a high level, with an obvious meaning, with fully general semantics that are the same on any fs/device that supports it. (In fact, I suspect that one of the special flags values was added because one of the lilo developers didn't know about NOACCESS, so instead of opening a device file NOACCESS to call an ioctl, he got new code added into the kernel to allow him to use a special value with open to pass through ioctl's to the parent device....) > 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. That's not a bad idea! The kernel itself would still have to be changed to work through this module (when present), but it should be much easier in that case to verify that the default behavior (without the module) is identical to current behavior, than if the change were implemented directly in the kernel. Also, combining this with the idea of an fs being able to report whether or not it can handle O_NOACCESS: You should be able to disable this support for an fs at compile time or (for FS's which are in modules) at load time. That should be trivial to add. It might also be worth providing a mount option to disable it at mount time even when it is compiled in and enabled at load time (so I could have it on, say, /mnt/linux/usr, but not /mnt/linux, or on /usr but not /, or whatever).