develooper Front page | perl.perl5.porters | Postings from March 2000

RFH [Request for Hero] to solve Perl's tmpfile races

From:
Tom Christiansen
Date:
March 6, 2000 10:11
Subject:
RFH [Request for Hero] to solve Perl's tmpfile races
Message ID:
21214.952366126@chthon
[I've widened the distribution because it's unfair to expect--and
unrealistic to hope--for Sarathy to fix everything Perlian by his
lonesome.]

			+----------------------+
			| HELP SAVE THE WORLD! |
			+----------------------+

 ********
 *  Careless or casual programs use temporary files in all kinds of
 *  unsafe ways, like placing them in world-writable directories, using
 *  predictable filenames, and not making sure the file doesn't already
 *  exist.  Whenever you find a program with code like
 *
 *        open(TMP, ">/tmp/foo.$$") 
 *           	or die "can't open /tmp/foo.$$: $!";
 *
 *  you've just found all three of those errors at once.  That program
 *  is an accident waiting to happen.
 ********

I'm afraid that we have a several of these accidents-in-waiting in
the standard distribution--albeit in utils only, not core C code;
thankfully.  I discovered perlbug to be replete with these and
uncountably numerous other errors.  But even perlcc and s2p have
the same issue.  While it would be nice if the greater Perl Community
in general were to become educated about this matter, it is most
critical that p5p contributors be well apprised of the ramifications
of this insidious practice.  Most importantly, we must never ship
a standard part of Perl that falls prey to it.

I believe that the optimal solution to this bug and the various
other tmpfile problems in the standard Perl distribution (cf perlcc
and s2p) is that one bundle standard an XS module called File::Temp,
which is an interface to (at least some of) the mktemp(3) family of
templating functions:

     char * mktemp(char *template);
     int    mkstemp(char *template);
     int    mkstemps(char *template, int suffixlen);
     char * mkdtemp(char *template);

It may be that the APIs should be slightly different so that you
can return a tuple.  Assume all input parameters are consts here.
(I've altered suffixlen to $suffix, as Perl has no problem counting,
but would certainly contemplate more natively-natural alternatives,
perhaps akin to File::Basename::fileparse().  Or perhaps not.)

    $unopened_tmpname = mktemp($template);
    ($pre_opened_tmpfh, $its_tmpname) = mkstemp($template);
    ($pre_opened_tmpfh, $its_tmpname) = mkstemps($template, $suffix);
    $tmpdir_name = mkdtemp($template);

Furthermore, because the tmpnam() and tmpfile() functions are
improperly implemented on some platforms (eg. they are *INSECURE*
on SunOS), these functions in the POSIX library should be replaced
with versions that call the appropriate underlying safe version
listed above.  That way Perl is not subject to the local C library's
bugs here, even for the non-templating versions (which aren't very
good ab initio, honestly, due to /tmp races).  Using

    @File::Temp::EXPORTS = qw/mktemp mkstemp mkstemps mkdtemp
			      tmpnam tmpfile/;

or some such, then have the bad programs use the appropriate one
of these instead.  A promiment and dire note should then be placed
in perlsec etc regarding this wretched matter.

We can include the available OpenBSD code for this in the Perl
distribution.  I have additional security measures for the functions
that return an unlinked descriptor that the Perl Hero who tackles
this should contact me about.

Yes, I am aware of the File::MkTemp module on CPAN.  I am also aware
that even after its recent updates, it remains a bad hack ridden
with bugs and security holes.  We need our own here trusted code,
written from scratch--and most simply as outlined above.

This doesn't resolve the many other bugs I have semiprivately pointed
out in perlbug, but it does address a critical security problem
more far-reaching than in just that particular program alone--a
problem, I hasten to note, which Perl has been previously called
to task on by the security mavens.

Who amongst you might provide us with a demonstration model of such
a File::Temp, and, using this new contrivance, patch the standard
Perl utils of their racey security holes?  I'm not saying that one
must have File::Temp for 5.6, as I am loth to delay its emergence
or add to Sarathy's burden.  But neither dare we ship standard
utilities that come complete with built-in security exploits lurking
within.  And if it's to be our eventual destiny to walk this path,
whether now or later, then as a certain doomed lord did once in
soliloquy remark:

    "If it were done when 'tis done, then 'twere well it were done
    quickly." :-)

--tom



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About