Xref: utzoo comp.unix.wizards:25375 alt.security:2419 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!uunet!stanford.edu!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: <1237:May321:05:0191@kramden.acf.nyu.edu> Date: 3 May 91 21:05:01 GMT References: <18924@sdcc6.ucsd.edu> <15369:May219:46:0491@kramden.acf.nyu.edu> <18953@sdcc6.ucsd.edu> Organization: IR Lines: 218 In article <18953@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes: > You missed the point. Your method boils down to avoiding using ptys (and only > works for ptys it will not work for real hardware ttys) that have background > jobs still using them. (It will work for hardwired ttys if you make the outlined changes to getty's initialization routine. But without a secure break key [as you can implement with my suggestion #24], hardwired ttys are completely insecure anyway.) Yes. Isn't it nice that the system also avoids using pipes that have background jobs still using them? > Better solutions are gained when alternative solutions are > investigated. I agree that it is worthwhile to investigate alternative solutions. But I really, really, really don't want to see someone call something a ``fix'' when it does not solve the problem on the vast majority of available systems. That's what you've been doing. I agree that vhangup(), revoke(), etc. would make a more useful (though more complex) security model, if they worked (which they don't in most current systems). That's why I've been pushing for an enforce() syscall. The problem is that to make vhangup() actually work as documented, you have to reorganize every file access in the system to go through the mechanism that vhangup() controls. Similarly for revoke() and enforce(). This is a worthwhile long-term project, not something you can reasonably require in a minimal fix. > ->Remember your article title was BSD tty security (not sunos pty security).<- Yes. The majority of BSD-derived multiuser systems ``out there'' are not SunOS machines. > On very active system with lots of background (or hung jobs) you eventually > run out of ptys. Without your {sleep, TIOCOPENCT ... loop} the service denial > hole is still present. This is something that is fairly important in > many environments. Again, I address this in the comments after step 12, as well as in step 7. For most environments it is not a problem, as there are typically ten times more ptys than background jobs. For the environments where this is not true, you will have to pay attention to my other suggestions. > My point is there a > an alternative to pty allocation that is less complex (the revoke() > suggestion encased in "exclusive use" ioctls is a lot simplier than the > complex setup and cleanup you are suggesting. Less complex? Less complex? Do you believe what you're saying? Would it be ``less complex'' if the system had a static pool of pipes? You pick a pipe, revoke() any current users of it, and then use it for yourself? Would it be ``less complex'' if the system had a static pool of pids? You pick a process id, fork(), revoke() any other processes with the same pid, and then use it for yourself? Would it be ``less complex'' if the system had a static pool of files? You pick an inode, revoke() any other users of that inode, and then use it for yourself? Sorry, but you're not being realistic. UNIX pipe management is simple because UNIX allocates pipes dynamically. UNIX pid management is simple because UNIX allocates pids dynamically. UNIX file management is simple because UNIX allocates files dynamically. Do you see anyone worrying about the security of pipes? That's why my solution effectively implements dynamically allocated ptys. ``Dynamically allocated'' doesn't imply infinitely many---you can run out of pipes or processes or files if you try hard enough---but it makes management and security much, much simpler. > It is easily stuck in > a library routine also and is a lot less code). How about we stop arguing, you write up a complete description at the same level of detail as mine, and then we see which solution is simpler and requires less code. > Tracking down all those references to a pty (or tty) is the SAME for > both your TIOCOPENCT and the revoke(). Incorrect. On a Sun, for instance, to handle TIOCOPENCT you just go from file descriptor to open file description to vnode, then report v->count of the vnode. Done. Your revoke() requires going through the entire file table and setting flags here and there. (That's what you said...) > Clearing and/or setting a flag > once you have found the references is trival. And once you have included special treatment of that flag in every single tty operation. This is a lot of kernel work. Why do you refuse to write out these changes at a sufficiently low level of detail that people can implement them? If it's so few lines of code, why don't you write out the code? > >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. > Neither p_ttyd (or u_ttyd) are in 4.3 RENO or earlier (and you did call > this a BSD tty security fix). Do you know what you're talking about? ttyd is standard BSD, and is on the vast majority of BSD-derived systems. ttyvp only appears on Suns, very recent (i.e. non-production) BSD releases, and possibly some obscure or extremely recently released systems that I'm not familiar with. I repeat my claim: your changes don't close the holes on anything but Suns and very recent BSD releases (such as Reno). In fact, unless you know you've changed every single tty operation to check that flag and behave properly, including when coming out of sleep, your changes are insecure even on those systems. > >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. > As stated above access rights are already checked on i/o ops, But you want people to add an extra check, plus have it handled for blocking processes. I repeat my claim. > On 4.3 RENO and earlier there is only u_ttyvp, so that replacement > is not needed. This statement is simply incorrect. On BSD 4.3 Reno and LATER there is u_ttyvp. I believe that they took the name and idea from SunOS, though I'll have to check this with Marc Teitelbaum. Damn it, I can't stay polite about this. You obviously aren't familiar with a wide range of machines---your statements about u_ttyvp prove that. Your fixes do not work on most machines, but you say they do because you don't know what you're doing. This is exactly the kind of sheer idiocy that has let to the current situation: nobody fixes the problem at its source, but people like you keep claiming that the latest kludge really does solve the problem, and fewer and fewer people realize that the problem still exists. I can't tolerate this! You are damaging security on present and future systems by claiming that an insecure solution is a solution. Don't you realize how stupid this is? When the problem is SOLVED, feel free to advocate further complexity in the security mechanism. In the meantime, don't be an ass. If you're going to propose a solution, check with more experienced people (like those at BSD) who can tell you whether it really will work. > >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(). > It is as easy (or easier) to make a setuid() program safe as it is to > preventing a server from crashing before it cleans up (so you state). That's what they said about Emacs. Ever hear of move-mail? > Having a pty "allocation" running as non-root causes problems. Perhaps you did not read my proposal. I require that *non-root* tty-handling programs be made setuid pty. This means programs like script. script already doesn't chown ttys; my changes don't affect this situation at all. This is the third time you've claimed that my changes break something when in fact they don't. Please read my proposal before criticizing it! > Things like mesg etc would > have to be setuid() pty to work. Again, please read my proposal before criticizing it! I have addressed practically every issue you've brought up. > A single user would be unable to access > another pty he was assigned by pty. There are many ways to pass data and descriptors. Furthermore, your statement about pty is incorrect; please read the pty interface definition in my pty paper, particularly the definition of -xc. > >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. > Sorry you are so sensitive about your design I'm not sensitive about it. I welcome constructive criticism of it. I'd love to see it made simpler without compromising its security. But I am extremely sensitive to your claims that you have a fix, when in fact YOUR CHANGES DO NOT SOLVE THE PROBLEM ON THE VAST MAJORITY OF SYSTEMS. This is the worst kind of security through obscurity: by claiming that your changes work, you might delude other people into believing you, and then they won't implement real fixes WHEN THE SYSTEM WITH YOUR CHANGES IS JUST AS INSECURE AS IT WAS BEFORE. Simplicity is a side issue when you can't even make correct fixes. > (I suspect many people > consider your proposal a kludge...). It is a kludge, albeit a reliable one. It's a kludge to fix a kludge. > In the environment BSD prior to 4.3 RENO revoke() works as > advertised (no process remains with any access after the revoke()), You are wrong. ---Dan