Ah, this looks like the old ungetc() exploit, where (back in the 1980s at utexas.edu) we'd leave a process connected to a terminal, wait for another user to log in, then push characters to their shell from our program using ungetc(). Essentially, each character pushed ends up looking like a fresh input character to the other program. The basic issue is whether all open file handles that shouldn't be there (our hack program, for example) got closed out by the new login session. For something like login, the question is easy, <i>ONLY</i> itself should be connected early on. For su, it's much weirder, since the user may have created background jobs before running su, and su and sudo can't reasonably close all other handles on the original tty device.<p>Further su and sudo can't close all file descriptors of the "sub-session" as it exits, because that the "sub-session" is created by forking, so su/sudo aren't around at the end.<p>Creating a separate pseudo-terminal device to allow for draconian cleanup, and prevent even having both user IDs connected to the same tty device, seems like the best place to start.<p>Hmm, now I want to go update the user-group-setter program I use (which also can set auth user IDs on Solaris, etc) and try having it do ptty allocation for the subjob.<p>In the meantime, try this to get a session and run through the same demo steps:<p><pre><code> setsid -w su - <user>
</code></pre>
Won't for <i>everything</i> (no /dev/tty), but it does block the example. You can add a tty if you have one handy, too, by using redirection in the spawned process in this general form, but I don't currently have the cluon for how to create a /dev/pts/<num> from the shell level - if someone can construct the full command, I'd like to see it :-)<p><pre><code> setsid sh -c 'exec command <> /dev/tty2 >&0 2>&1'</code></pre>