http://qs321.pair.com?node_id=51669


in reply to is I/O checking worth it?

The first step if security matters is to read perlsec and then turn on taint checking.

A good step regardless is to have every open test what you did. I believe in doing it like perlstyle says and having the error message include the filename, attempted operation, and $!.

If you need to read and write files but don't want to follow symlinks, this can get fairly tricky. The following code (which will fail horribly on systems without symlinks) demonstrates how to do it safely:

#! /usr/bin/perl -w use strict; use Carp; use Symbol; # Needed on 5.005 and less sub clear_file { my ($fh, $name) = @_; seek($fh, 0, 0) or confess("Cannot seek to beginning of '$name': $!" +); truncate($fh, 0) or confess("Cannot truncate '$name': $!"); } sub deny_symlink { my ($fh, $name) = @_; # In the following testing the filehandle avoids a race # condition, but I think that whether it works is OS # specific. :-( if (-l $fh or -l $name) { my $real = readlink($name); confess("Refusing to follow symlink from $name to $real"); } } sub open_read { my $name = shift; my $fh = gensym(); open($fh, "< $name") or confess("Cannot read '$name': $!"); deny_symlink($fh, $name); return $fh; } sub open_write { my $name = shift; my $fh = gensym(); open ($fh, "+>> $name") or confess("Cannot write '$name': $!"); deny_symlink($fh, $name); clear_file($fh, $name); return $fh; } my $filename = "whatever"; *FH = open_write($filename); print FH "Hello world\n"; close FH; *FH = open_read($filename); print <FH>;
In general if you need temporary files, do not attempt to roll that yourself. Use File::Temp. Really.

Also note that if you are concerned with security then you may want to think about locking. For an example (which could easily be improved) that I came up with a while ago see Simple Locking.

With luck this should give you some ideas of how to improve the security of your programs.