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

Hi, I have a script that needs to find out where it was executed from. The following script:
#!/usr/bin/perl -w
print "$0\n";
normally works ok. However, if the script is set-uid (to any user) it prints something like "/dev/fd/3". This is under Solaris 2.7. The FindBin modules uses $0 as its starting point, so it doesn't work either.

I read somewhere that this is a trick used by some kernels to safely execute set-uid scripts: when a set-uid script is invoked, the kernel passes the script to the interpreter using a file descriptor instead of the file name directly, to avoid race conditions. If this is the case, my problem may be unsolvable, but I thought I would ask anyway.

I asked in comp.lang.perl.misc about this, and got two main suggestions, which I list with their drawbacks:

So I'm still looking for a real answer to my question. Any ideas will be very appreciated!



  • Comment on How to determine the program path from a set-uid program

Replies are listed 'Best First'.
Re: How to determine the program path from a set-uid program
by plaid (Chaplain) on Mar 30, 2000 at 02:15 UTC
    After looking around on a Solaris box for a bit, I've also come to the unfortunate conclusion that there isn't really anything you can do. There seems to be no trace of the actual command typed anywhere. ps reports the pid as running /usr/bin/perl -w /dev/fd/4, and the lack of a decent /proc system on Solaris is also a dead end. If you are forced to pick, the latter of the two choices above sounds like a safer bet... always better to not have to deal with taint-checking of any external variables in a program, especially an suid one.
Re: How to determine the program path from a set-uid program
by mikfire (Deacon) on Mar 30, 2000 at 03:18 UTC
    I have found this works quite well as a work-around.

    Wrap all calls to perl into a binary that is SUID. At the top of any script needing to go suid, put something like:

         eval 'exec /usr/local/bin/perlwrap $0 {$1+"$@"}'
         if 0;
    where /usr/local/bin/perlwrap has the SUID bit correctly set. The name the script was actually called as ( including the path component ) and all the remaining command line arguments are sent to the wrapper as arguments. The wrapper does the SUID stuff and then runs the script, passing along the arguments. Since the script itself was never SUID, you don't get the file descriptor problem.

    You can then use a special ID to control which scripts can and cannot go SUID. Basically, if the script isn't owned by the special ID the permissions get reset to the user's before the script is run.

    If you need more help, email me and I will do what I can.

    Mik Firestone ( perlus bigotus maximus )

Re: How to determine the program path from a set-uid program
by btrott (Parson) on Mar 30, 2000 at 01:39 UTC
    You read correctly re: the security issue. In fact, this very information is found in perlsec. So, unless you're willing to use a wrapper script of some sort (which, it seems, could have the disadvantage of making your program insecure anyway), I don't think there's a solution to your problem. Sorry.
Re: How to determine the program path from a set-uid program
by turnstep (Parson) on Apr 01, 2000 at 07:17 UTC
    I'm able to duplicate the problem easy enough, but I can also get the name of the script through the web from Apache which sets the variable $ENV{'SCRIPT_FILENAME'}. I can also get it from the command line by looking at the value of the environment variable "_". This was on a fairly old sparc, so it may help, or may not.