[comp.bugs.4bsd] Interactive shells in emacs: a security problem?

mattson@beowulf.ucsd.edu (Jim Mattson) (08/23/89)

When I run an interactive shell in GNU emacs or Jove, the editor provides me
with a pty that looks like this:
crw-rw-rw-  1 root      10,   4 Aug 22 17:31 /dev/ttyp4

Of course, the editor cannot run setuid root, so it cannot change the owner
or mode of the pty.  Unfortunately, it is possible for someone else to
run a program that:
  a) detaches from its controlling terminal
  b) opens _my_ pty RDWR  (establishing it as the controlling terminal)
  c) uses TIOCSTI to stuff characters into my psuedo-terminal input

As a result, my interactive shell is at everyone's mercy.  I might as well
post the password to my account.

It seems that this is an inherent problem in the way 4BSD programs use ptys.
If the program does not run setuid root, it cannot guarantee the security
of the pty connection.  Maybe there should be an ioctl that allows a
regular user to make himself/herself the owner of an open pty connection.
That seems really awful, though.  Are there other solutions?

--jim
  

mark@umbc3.UMBC.EDU (Mark Sienkiewicz) (08/23/89)

In article <6973@sdcsvax.UCSD.Edu> mattson@beowulf.UCSD.EDU (Jim Mattson) writes:
>
>When I run an interactive shell in GNU emacs or Jove, the editor provides me
>with a pty that looks like this:
>crw-rw-rw-  1 root      10,   4 Aug 22 17:31 /dev/ttyp4
...
>As a result, my interactive shell is at everyone's mercy.  I might as well
>post the password to my account.
...
>of the pty connection.  Maybe there should be an ioctl that allows a
>regular user to make himself/herself the owner of an open pty connection.
>That seems really awful, though.  Are there other solutions?

You could arrange for the pty device driver to change the owner of the 
tty?? file for you.  Suppose the steps looked like this:

1) emacs (or whatever) opens ptyp0 to use as a master for an interactive shell.
2) the driver notes the uid & gid of the emacs (or whatever) process.
3) A child processes is created which opens ttyp0 for it's control terminal.
   The pty driver does a little tracing back through the kernel structures
   to find the inode (in core, of course) for ttyp0 and changes it's owner
   fields to match the owner of the process that allocated the pty.
4) the last close of ttyp0 changes the owner back to root and the permissions
   back to 0666.

Then the only responsibility remaining for the user program is to fix
the protections after allocating the pty.  

Doing something like this should be relatively painless except for finding
the inode that open was using.  Even for that, you could brute force search
all in-core inodes for something that matches the major/minor number that
was handed to ptyopen().  I can see 2 problems with this approach:

1) it's kind of a non-elegant way to do it.  device drivers aren't really
	supposed to mess with things like that.

2) If you do 2 mknod's for the same minor number of a tty device, you
	can see your original problem come back.  Don't do this.

Anybody see why this should'nt work?


-- 
			Mark S.

uunet!umbc3!nerwin!zilla!mark
nerwin!zilla!mark@umbc3.umbc.edu

srg@quick.COM (Spencer Garrett) (08/24/89)

In article <6973@sdcsvax.UCSD.Edu>, mattson@beowulf.ucsd.edu (Jim Mattson) writes:
-> It seems that this is an inherent problem in the way 4BSD programs use ptys.
-> If the program does not run setuid root, it cannot guarantee the security
-> of the pty connection.  Maybe there should be an ioctl that allows a
-> regular user to make himself/herself the owner of an open pty connection.
-> That seems really awful, though.  Are there other solutions?

Sure.  Just set TIOCEXCL on the master side when you open it, and refuse
to spin off a shell until that call succeeds.

benson@odi.com (Benson I. Margulies) (08/27/89)

In article <2255@umbc3.UMBC.EDU> mark@umbc3.umbc.edu.UMBC.EDU (Mark Sienkiewicz) writes:

Here's how Multics dealt with this class of issues:

First: all terminal devices were owned by the Initializer. (think of
it as init.)

Second: if a user process wanted a terminal, like a dial-out or 
a pty-equivalent, it had to ask the Initializer via IPC. (imagine
a server on a Unix-domain socket.)

Third: When a user got a terminal, they only got it until it hung up
or their process went away. Then the Initializer regained control and
got to reset the thing to a clean state.

Fourth: for pty-like entities, which I have to admit were not
extensively used by nonprileged code, the two ends were maintained
in suitable access control parallel.

I've always thought that Unix needed a pty allocation management
scheme, to avoid problems of hogging, to avoid access control problems,
and to get utmp and such management to work without any setuid stuff.