BSD tty security, part 3: How to Fix It

Dan Bernstein brnstnd at kramden.acf.nyu.edu
Tue May 7 06:55:53 AEST 1991


In article <19249 at rpp386.cactus.org> jfh at rpp386.cactus.org (John F Haugh II) writes:
> There is absolutely =no= reason to consider hardware tty's to be
> insecure simply because they are hardware tty's.  All that is required
> to make hardware tty's secure is for some operation to exist which
> insures that all current references to the device are legitimate.

Agreed. Since UNIX doesn't provide for revoking a valid file descriptor,
the obvious solution is to make sure that no user program ever gets to
touch a modem driver. A privileged program can control the driver and
route I/O through a pipe or pseudo-tty or socket or any other basically
dynamic object. It can also drop its control of the driver whenever the
user types break.

> This could be implemented as a hardware signal (Secure Attention Key)
> which kills all processes on the list of processes having the device
> open directly or indirectly but not possessing some privilege or
> belonging to some set or processes.

The problem is that, once again, UNIX doesn't have this concept of
terminating current access. The last time that people tried to add it to
BSD was vhangup(), and that was a complete failure.

I find it conceptually much simpler to just make sure that unprivileged
programs never open /dev/modem*.

> >In particular, your ``fixes'' do not work on any system that has
> >p_ttyd/u_ttyd instead of u_ttyvp. This includes most BSD releases,
> >Ultrix through at least 4.1, Convex UNIX through at least 9.0, and many
> >other systems. So if you're going to continue talking about your
> >``solution'', please try to be accurate: ``solution for BSD 4.3-Reno''.
> It is very possible to have u.u_ttyd and still have secure hardware
> tty ports.  The system could very easily maintain a list of every
> process which has any reference to that specific device.

Well, sure, but that's even more work that Muller hasn't outlined in
detail. Again it seems much simpler to put this control at the user
level.

> >Don't you understand that this ``termination'' idea is foreign to UNIX?
> >Don't you think that you'd better have a whole bunch of people think
> >through it and reimplement the kernel around it before deciding that it
> >works?
> This has already been done several times.

Fine. If it works in AIX then that's good for AIX. Unfortunately, most
machines out there don't have kernels supporting termination.

> The complaints you have about "future" termination are really very
> easy to address.  There are only so many places a process can sleep
> in a device driver.  Go fix them.

And how about file descriptor passing, which is yet another path for a
file to stay open past revocation?

The basic problem here is that inside the kernel valid file access can
be represented in many different forms. The *only* time access
permissions are checked is when the access goes through an open file
table entry. To chop off file access, you have to chop off every
possible form of that access---even if it's hidden inside a blocked
syscall or a message.

One way to fix this in the long term is to have permissions at a lower
level than open file descriptions---permissions at such a low level that
*every* file operation will check them in every time slice where they
apply. In a vnode-based system, one example of such permissions is the
filesystem pointer, and BSD 4.3-Reno has a working (though not very
fine-grained) revoke() that simply trashes that pointer.

Switching to vnodes is, unfortunately, too much to require in a minimal
fix. In the long term it would seem wise to consider exactly what sort
of permissions should apply at a lower level than open file access, how
those permissions should be controlled, etc.

> >Here, let's review my required kernel changes again:
> [ List deleted ]
> >Would you like to give a paragraph stating your required changes, at the
> >same level of detail?
> Provide a mechanism within the kernel for tracking processes with
> current access to any inode table entry.

C'mon, that's not at the same level of detail as ``Make /dev/tty ioctls
work on /dev/tty??''. *What* is the mechanism? You obviously have to
introduce some new structures or add fields to the old ones; where are
those fields?

To make this work on current systems you also have to make sure that
u_ttyd access is tracked. This would require that an entirely separate
set of kernel routines be changed, and I don't think a whole bunch of
people would figure this out from your description.

---Dan



More information about the Comp.unix.wizards mailing list