Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
 

Introduction

 

This meditation/module review has been written in response to a node recently where a user was generating a list of files for process iteration through use of a temporary file. In addition to this, the temporary file being generated for this task was of a fixed file name, compounding security issues involving temporary file usage on shared systems. Now while the motivation for this meditation and module review was born out of a review of code logic, it is not my intention to evaluate the code with provoked my thoughts, but rather to discuss available options for the generation and utilisation of temporary files in a secure fashion.

 

Basics of Temporary Files

 

As with all things with Perl, the pragma of there being more than one way to perform any given task holds true for the generation and utilisation of temporary files within Perl. The most basic and direct way to create a temporary file for usage within Perl would be something similar to the following:

local *FH; open (FH, ">/tmp/myprocess.tmp") || die "Cannot open temporary file: $ +!\n"; ... close FH;

... or using the more friendly IO::File module ...

use IO::File; my $fh = IO::File->new("/tmp/myprocess.tmp", "w"); if (defined $fh) { ... $fh->close; }

While simple in logic and process, it is unlikely that code such as the above would be incorporated into any production Perl project utilising temporary files, particularly where sensitive data may be stored in such files. The reason for this is that using a predictable filename such as this makes the task of hijacking information stored in these files relatively straight-forward for a user with malicious intent either through pre-creating the requested file in the (presumably) world-writable directory or establishing a named pipe to another process. Some of these issues are also discussed in the perlsec page under the "Security Bugs" heading.

In order to minimise the likelihood of such maligned user interference with process execution and temporary file utilisation, some code authors have additionally employed temporal and system variables such as time and $$ in temporary file names. While complicating the process for users maligned intent it is still relatively straight-forward to implement predictive measures to attempt to hijack or interfere with data written to temporary files - The exception to this rule would be on OpenBSD systems where process id is randomised, but nevertheless, the potential still exists.

 

Non-Predictive Temporary Filenames

 

The solution to this process is to utilise methods for temporary file generation that produce non-predictable file names. Temporary files of this nature are far-less susceptible to corruption or interference.

There are a number of ways by which such non-predictable temporary files can be generated under Perl in a safe, secure and portable fashion. The first is through the use of the tmpnam function exported from the POSIX library on supported systems. An example piece of code using this function for temporary file generation should look like this:

use Fcntl; use POSIX; my $name; do { $name = tmpnam(); } until sysopen(FH, $name, O_RDWR|O_CREAT|O_EXCL, 0666);

Note that there are still some issues with the usage of the tmpnam function on a basic level relating to race conditions which may occur between the generation of the temporary file name by the tmpnam function and the generation of the file by the calling process. Additionally, the calling process has no control as to the location of the created temporary file meaning that the created file could end up in a world writable directory on a system that doesn't honour sticky-directories - These issues were discussed in a comp.lang.perl.moderated newsgroup thread here and on a BUGTRAQ post from Tom Christiansen here.

An alternate method for the creation of temporary files in Perl is through the new_tmpfile method exported from IO::File - An example piece of code using this function for temporary file generation should look like this:

use IO::File; my $fh = IO::File->new_tmpfile;

This module creates a temporary file, based on the POSIX tmpfile() function or tmpfile() from glibc if using Perl I/O abstraction, and then, where possible, unlinks the file while still holding it open. The result is an anonymous file handle suitable for the temporary storage of data - The data is stored in a stdio stream. The only disadvantage with this method of file name generation is that the temporary file cannot be referenced other than through the returned file handle.

Another method for generating temporary files in a secure and portable fashion is through the File::Temp module - Most interestingly, this module makes use of XS functions to implement the *BSD mk*temp() set of library functions in addition to exported variants of glibc functions mktemp(), tmpnam() and tempnam() and POSIX functions tmpnam() and tmpfile(). The File::Temp function also introduces a package variable safe_level which specifies the lengths that the File::Temp module will go to check the safety of a temporary file or directory before making use of it.

Explore the documentation for File::Temp here.

 

Suggestions, comments, directions for evaluation?

 

perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'


In reply to Using Temporary Files in Perl by rob_au

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2024-03-28 11:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found