Search code examples
perlunixaccess-rights

Why the file-test operator does not work (Perl)?


In "Programming Perl" -w file-test operator described as:

–w File is writable by effective UID/GID.

I have two files:

-rwsrwxrwx 1 testuser testuser 226 Jul 20 20:31 script.pl
-rw-rw-r-- 1 testuser testuser  34 Jul 14 17:24 file.txt

suid is set on script.pl, so when I run it as user caligula, effective UID/GID should be the testuser's one. script.pl is:

#!/usr/bin/perl
use v5.14;
if (-w 'file.txt') {
    say "true";
}
else {
    say "false";
}

But when I run it caligula@ubuntu-host:~$ ./script.pl the output is always false. Why does that happen, may be I didn't understand the correct usage of that operator?

My appreciation.


Solution

  • Perl can be configured so that SUID scripts are ignored; it is the default, and likely how yours is set up. You should print the real and effective UID and GID in the script.

    You can validate this concretely with a modestly obscure Perl one-liner:

    $ perl -MConfig -e 'foreach $key (keys %Config) { print "$key = $Config{$key}\n"; }' |
    > grep -i -e 'se*t*[ug]id'
    d_dosuid = 
    d_setresgid = define
    d_setresuid = define
    d_suidsafe = 
    $
    

    Or, slightly less obscurely now I've found the right name:

    $ perl -MConfig -e 'print "d_suidsafe = $Config{d_suidsafe}\n"'
    d_suidsafe = 
    $
    

    This shows that this Perl (a 5.12.1 that I built) does not regard SUID scripts as safe.

    The real and effective user and group ID values are reportable with: RUID $<, EUID $>, RGID $( and EGID $), or (more sensibly) using English:

    #!/usr/bin/env perl
    use English '-no_match_vars';
    print "EUID = $EUID; RUID = $UID; EGID = $EGID; RGID = $RGID\n";