Xref: utzoo comp.unix.wizards:25340 alt.security:2407 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!think.com!hsdndev!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: comp.unix.wizards,alt.security Subject: Re: BSD tty security, part 3: How to Fix It Message-ID: <15369:May219:46:0491@kramden.acf.nyu.edu> Date: 2 May 91 19:46:04 GMT References: <7299:Apr2510:22:2091@kramden.acf.nyu.edu> <18924@sdcc6.ucsd.edu> Organization: IR Lines: 77 In article <18924@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes: > While this may look useful for patching an existing system, it might be more > profitable in the long term to step back from the details of the current > problem and investigate the underlying problem with ttys. The only unusual aspect of my solution is TIOCOPENCT, which is sufficient to simulate dynamic ttys with static ttys. Making the tty files inaccessible and making programs setuid is a standard technique. Replacing /dev/tty with my /dev/stdtty is necessary (on systems without u_ttyvp, anyway) to close the avenue that gets around most ``fixes.'' Together these changes *do* solve the underlying problems of statically allocated ttys, though I would prefer that ptys be as dynamic as pipes in the first place. > I really do not want > to depend on the actions of step 9 (especially step 9c....) to promote > security (what if the master side process dies prematurely for example; not > all servers can be that robust all the time). I address this in the comments after step 12. You can, for instance, arrange for each process to skip a tty during allocation if TIOCOPENCT indicates that the file is in use. However, this added complexity is not strictly necessary, and on most machines the servers really don't crash. If you have the time and energy, by all means add TIOCOPENCT checks at the beginning of each session. > This also greatly increases > the complexity of servers (even if it is in a library) and divides the task > of resource protection between the kernel and numerous user processes in > a complex way. The complexity is already there! A typical BSD system has a dozen programs managing the pseudo-tty resources. This type of decentralized management is stupid, and it makes any tty fix much harder to apply, but my fixes certainly don't make the situation any worse. If someone takes the time to rewrite telnetd (well, I've done this already) and rlogind and expect and so on to use a single, modular pty manager (e.g., my ``pty'' program), then he'll be able to implement my fixes just by adding TIOCOPENCT and changing that manager in the way I've described. But this is way too complex for a minimal fix. > Since kernel changes are being proposed in the above > solution, maybe a different approach would provide a less complex solution. Your solution requires many more changes than mine, and most of them in the kernel. It does not provide or simulate a simple model like dynamic ttys. It is not spelled out in sufficient detail for someone to implement, and the effects of each change are not explained. Most importantly, your changes don't close the holes on anything but Suns and very recent BSD releases. Should I explain this? All your revoke() does is stop access through the open file table (and it's not entirely clear that it will work any better than vhangup() for that). But p_ttyd (or u_ttyd) doesn't *go* through the open file table. Poof, there goes your security. You also require that a flag be added to the file structure and that every single tty I/O operation be changed to pay attention to that flag and take special action if it is set. So far (not to mention replacing u_ttyd with u_ttyvp or the equivalent) we're talking about some hundreds of extra lines of kernel code---far more than required to implement /dev/fd/3 (to replace /dev/tty) or TIOCOPENCT. You require that all tty-handling programs be setuid root. Setuid to some other uid would be much safer---but you can't do that without letting unprivileged users abuse revoke(). I'm sorry to criticize your changes in such harsh terms, but they remind me too much of the kludge upon kludge that vendors like Convex have tried. You don't stop the problems at their source; you let two independent user programs have a tty simultaneously open; your changes don't even work as advertised on most machines, because you missed a fundamental avenue around your revoke(). Even if your fix were simpler or less fragile than mine, these flaws would condemn it. ---Dan