Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-92641

perl cannot resolve "$0" and reports /proc/PID/fd/6 as "$0" instead of script name, when script executes under sudo + checksum verification

Linking RHIVOS CVEs to...Migration: Automation ...SWIFT: POC ConversionSync from "Extern...XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Critical Critical
    • rhel-10.2
    • rhel-8.10, rhel-9.6, rhel-10.0
    • perl
    • None
    • No
    • Critical
    • ZStream
    • rhel-stacks-services-scripting
    • ssg_core_services
    • 0
    • False
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • Approved Blocker
    • None
    • None
    • Unspecified
    • Unspecified
    • Unspecified
    • None

      When executing a perl script under sudo and sudo has a line to verify the checksum, then the $0 is reported as /dev/fd/6 instead of script being interpreted, which is expected. However resolving the file descriptor doesn't work because the file descriptor got closed already early by perl interpreter, as shown in the example below.

      perl script /usr/local/bin/script.pl

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      use Cwd qw( abs_path );
      
      print "\$0: $0\n";
      print "abs_path(\$0): " . abs_path($0) . "\n";
      

      configure sudo to verify the checksum

      # echo "user ALL=NOPASSWD: sha256:$(sha256sum /usr/local/bin/script.pl)" > /etc/sudoers.d/user
      

      execute the script under sudo

      (user) $ sudo /usr/local/bin/script.pl
      $0: /dev/fd/6
      abs_path($0): /proc/9839/fd/6
      

      Having /dev/fd/6 is expected because sudo makes use of execveat() to execute the script, instead of "regular" execve(), as seen with stracing:

      9837  12:51:09.752045 execve("/usr/bin/sudo", ["sudo", "/usr/local/bin/script.pl"], ...
       :
      9839  12:51:09.794910 execveat(6</usr/local/bin/script.pl>, "", ["/usr/local/bin/script.pl"], ..., AT_EMPTY_PATH) = 0
       :
      

      However, internally, as soon as Perl starts, the file descriptor gets closed, causing abs_path() to not be resolvable into the script name:

       :
      9839  12:51:09.799366 read(6</usr/local/bin/script.pl>, "#!/usr/bin/perl\n\nuse strict;\nuse warnings;\n\nuse Cwd qw( abs_path );\n\nprint \"\\$0: $0\\n\";\nprint \"abs_path(\\$0): \" . abs_path($0) . \"\\n\";\n", 8192) = 135 <0.000006>
      9839  12:51:09.805321 read(6</usr/local/bin/script.pl>, "", 8192) = 0 <0.000008>
      9839  12:51:09.805344 close(6</usr/local/bin/script.pl>) = 0 <0.000007>
       :
      9839  12:51:09.805383 write(1</dev/pts/0<char 136:0>>, "$0: /dev/fd/6\n", 14) = 14 <0.000116>
      9839  12:51:09.805814 write(1</dev/pts/0<char 136:0>>, "abs_path($0): /proc/9839/fd/6\n", 30) = 30 <0.000033>
      

      Due to this bug/limitation inside Perl, it's impossible to know which script is currently executing.

              mspacek@redhat.com Michal Josef Spacek
              rhn-support-rmetrich Renaud Métrich
              Mason Loring Bliss
              perl-maint-list perl-maint-list
              Martin Kyral Martin Kyral
              Votes:
              0 Vote for this issue
              Watchers:
              15 Start watching this issue

                Created:
                Updated: