Rhandom has asked for the wisdom of the Perl Monks concerning the following question:

All documentation about taint explains that "taint" mode may be enabled by using the switch -T on the perl commandline. Fair enough. Easy enough.

Some documentation then goes on to say that enabling of taint must happen as near the beginning of the script as possible to prevent access to tainted data - such as PERL5LIB and PERLLIB and so on. Ok - that is logical and reasonable.

My first question is: Is there a way to enable taint during Runtime? Essentially can I enforce limits at a later point in time like I might do with a BSD resource (granted that once the limit is put in place it cannot be removed) ?

My guess is that the answer is "No," not without some XS that sets flags in the internals. Most likely there is something setup different in the interpreter which handles dangerous calls differently and this is probably done at program initialization.

Which kind of leads to the second question: Is there a sane variable that I can check to see if taint is enabled?

Again, from the documentation I've read the answer seems to be "No," not without some XS that checks the internal flags. I know that it is possible to determine if taint is on by "probing the fence" (by generating tainted data and then eval{}ing it with a dangerous call - which is what the Taint modules generally do). There must be a flag somewhere that is set. I'm just wondering if that flag is visible.

I can think of many reasons why what I'm asking for is bad. Any reason I could think for wanting to do so could probably be easily countered with a reason why I should not. Read any the documentation and you can discern reasons why you wouldn't want to be able to do this in normal circumstances.

The common responses could be "Why wouldn't you just enable taint from the beginning - if you need it at the end you should have it at the beginning" and "Why do you need to check if taint is on - if you need to check if taint is on you should've been checking your data all along anyway in which case you'll be safe." These are good and valid responses and are certainly welcome.

But I am not as much interested in "Why you shouldn't" do these things, as I am interested in "Can you." My guess is, if the answer is "You cannot" then the reason is/was "Because you should not."

An answer of "You cannot" seems odd to me though. Perl doesn't normally keep you from doing dangerous things, even though they are dangerous.

PS - I don't have an example in mind. I'm just testing possibilities.

Update:
P.PS - The following is one way - but it is ugly. I'd much rather prefer something that I could call without re-execing (plus there is the problem of getting back to the same place in the script). Speaking of which, if I can do this, then any argument for preventing me from doing it from within the code sort of becomes mute:
exec('perl', "-Mlib=$ENV{PERL5LIB}", '-T', $0, '--taint_exec', @ARGV);


my @a=qw(random brilliant braindead); print $a[rand(@a)];

Replies are listed 'Best First'.
Re: Runtime Taint Enable
by VSarkiss (Monsignor) on Feb 23, 2005 at 23:18 UTC
      I wasn't aware of ${^TAINT} - that is nice. Any of the modules that have an is_tainted function can be passed known "bad data" such as join("",$0,%ENV,@ARGV) or a few characters from /dev/urandom. But each of these is_tainted functions have to probe by trying to do something bad. Some use eval "#$baddata", others try and do kill 0 * $baddata. It would be nicer to just check the flag. It would be even nicer if I can set the flag to on (knowing I can't turn it off). I think I'll go give it a try.
      perl -T -e 'print "(${^TAINT})\n";'
      Works on perl 5.8.5 but not on 5.6.0.

      my @a=qw(random brilliant braindead); print $a[rand(@a)];
Re: Runtime Taint Enable
by BrentDax (Hermit) on Feb 23, 2005 at 23:30 UTC
    An answer of "You cannot" seems odd to me though. Perl doesn't normally keep you from doing dangerous things, even though they are dangerous.

    While this is true, taint checking is something of a special case. When you turn on taint checking, you're specifically asking Perl to stop you from doing certain kinds of dangerous things. One of those dangerous things is to turn on tainting in the middle of your program--at that point it's essentially useless, because things that should have been tainted aren't! Hence, you're not allowed to turn on tainting in the middle of your program.

    As the previous poster mentioned, you can use the ${^TAINT} variable to check if taint checking is turned on. (But as you implied, I'd recommend against doing so--there's nothing you should do when -T is on that you shouldn't also do with it off.)

    =cut
    --Brent Dax
    There is no sig.

      As a devil's advocate and ignoring problems with PERLLIB and PERL5LIB, in a CGI enviroment I can do many things before I read any input from the user. So as long as taint is enabled by the time I read input from the user then the dangerous data is taken care of. There are only so many sources of input to control and it is an easy process to mark untainted items as tainted.

      Thanks for your response. ++ to you.

      my @a=qw(random brilliant braindead); print $a[rand(@a)];

        Hmm, interesting: I confess I don't use tainting in my CGI scripts despite the common recommendations, and this is part of the reason why - the data sources I want to choose not to trust are a small fraction of the whole, and the maintenance cost of detainting everything seems too high to me.

        With the caveat that perl is not written with the intention of supporting this, I found the following simple test gave me the results I expected:

        #!/usr/bin/perl -w use strict; use Scalar::Util qw/ tainted /; use Inline C => 'void starttaint() { PL_tainting = 1; }'; my $line = <>; print "line tainted: ", tainted($line), "\n"; print "\$0 tainted: ", tainted($0), "\n"; starttaint(); $line = <>; print "line tainted: ", tainted($line), "\n"; print "\$0 tainted: ", tainted($0), "\n";

        It is trickier if you want to taint a data structure after having turned on tainting late: the normal way to taint a variable is to wave another already-tainted variable at it, but in this case you might not have one. The simplest way to achieve that is to add another Inline function to create one:

        SV* taintvar() { PL_tainted = 1; return newSVpvn("", 0); } ... # perl code starttaint(); my $tv = taintvar(); sub taintme { wantarray ? map($_ .= $tv, @_) : $_[0] . $tv }

        I repeat, perl was not written with the intent of supporting such usage, and the behaviour may easily change between perl versions, platforms and phases of the moon.

        Hugo

        I agree. It's useful to provide configuration information through the environment, and there's no danger (as long as you don't use environment variables that are set automatically based on the Web request).

        I often simply blindly untaint data from environment variables I know are safe, and convert PERL5LIB into a series of use lib commands. That's the technique I would recommend.

        It would be useful if Perl's mechanism for handling tainted data was more flexible, to better handle these situations.

        You assume that users are the only place to get tainted data from. Any external data can (and should) be marked as tainted. This includes but is not limited to: the results of system calls, database results, and anything that is derived from these. Basically, anything that came from outside your program should be viewed as suspect when thinking about taint.

        thor

        Feel the white light, the light within
        Be your own disciple, fan the sparks of will
        For all of us waiting, your kingdom will come

      One of those dangerous things is to turn on tainting in the middle of your program--at that point it's essentially useless, because things that should have been tainted aren't! Hence, you're not allowed to turn on tainting in the middle of your program.
      That makes a lot of sense, but only if you're a god, and the start of a Perl program is the creation of the world. In reality, it's different. A system gets booted. It does a lot of things, including getting user input. After some time, a program is started with taint checking on. By stepping out the little box that your perl program is, you essentially are turning on taint checking in the middle of something.

      If that's ok, then turning taint checking on halfway your program should be fine too. For example, take an init.d script that first runs some (shell) commands, then starts a daemon written in Perl, using -T. From a conceptual view, tainting is turned on sometime after the script was started. And perhaps if you were to replace it with just one larger Perl program, you want to turn on taintchecking at the same point.

      I think the programmer should have finer control over what's considered tainted or not. Currently, it's all or nothing. But a daemon listening on some port might consider its environment, and any file it reads from the system safe (no need to untaint). But not what it gets from a socket. Or a program doesn't want to taint keyboard input, but it does consider the stuff it reads from the database to be tainted.