Re: another /tmp race: `perl -e' opens temp file not safely

stanislav shalunov (shalunov@MCCME.RU)
Sun, 08 Mar 1998 08:38:20 +0000 (GMT)

This is starting to get off topic, I am afraid, but still...

>>>>> "deraadt" == Theo de Raadt <deraadt@cvs.openbsd.org> writes:

>> All this complexity of trivial things (just open a temp file) is
>> one of the reasons I think the whole idea of /tmp is a fundamental
>> misdesign and eventually one should be able to chmod it to 755
>> (while programs should use per-user TMPDIRs).

deraadt> Which, as I've said before, works REALLY well for setuid
deraadt> programs.
deraadt> Imagine:
deraadt> TMPDIR=/
deraadt> Or how would you solve that problem?

You probably mean rather something like
TMPDIR=$HOME/tmp privileged & symlink_exploit
or I did not understand your argument.

In fact what I had in mind was _not_ honoring TMPDIR environment
variable but rather some fixed-dir mechanism (or at least TMPDIR does
not to be set by default but supported for flexibility--/home almost
full or want to use a local drive rather than something NFS mounted).
The good old 1777 /tmp is still necessary in Unix environments (to get
rid of the beast completely one will have to change a lot of stuff).
The pseudocode to decide where to store temp files might look like
(its place is in the function that all mktemp style functions call):

home = euid's home dir from /etc/passwd
homeok = ((home is writable for euid) and
(home/tmp doesn't exist or is a dir writable for euid))
groupok = (egid == gid) or (euid != uid)
noprivs = (egid == gid) and (euid == uid)
if noprivs and environment TMPDIR is set then
tmpdir = $TMPDIR
if tmpdir and everything above is writable only by their owners then
safe = true
else
safe = false
fi
else if homeok and groupok then
tmpdir = home/.tmp
safe = true
else
tmpdir = /tmp
safe = false
fi
if tmpdir doesn't exist then
/* They could spot a race here, but what for? Or are there
any OSes that will follow symlinks creating dirs? */
success = mkdir tmpdir with perms 0700
assert success
fi
if not safe then
make all calls not considered secure log something
/* logging without openlog() first */
fi
generate unique filename in tmpdir
...

Well, something like this. It should make most /tmp problems go away.
The only programs that will still be vulnerable with this approach--if
they do not use (a call using) O_EXCL--will be those that are setgid
or those that are setuid to a user with a wierd home (like bin or
httpd or ftp). So, in practice, only setgid programs (because of the
fact groups do not have homes) and third party stuff with hardcoded
/tmp will be suspect. There is only a very limited number of setgid
programs. And they all are in the OS so they can be audited. Many
problems with third-party software are solved (if some third party
program has /tmp hardcoded and insists on insecure running you'll at
least get log notices).

With this approach you win some robustness and lose nothing (except
inodes for ~/.tmp--like 500K of disk space on a machine with 1000
users and a reasonable filesystem as ~/.tmp will normally be empty
[clean them on boot and delete files with [ca]time a few days old via
a cron job]).