skip to Main Content

I have a custom build of apache’s httpd version 2.2 together with perl version 5.22 on solaris 10. The httpd runs in a chroot environment, and the perl script is executed via httpd’s mod_cgid. So far all was in 32 bit things worked. Now I have compiled everything in 64 bit (because another httpd module is only provided as a 64 bit binary), and now I cannot get the perl script to be executed via cgid.

The http error log contains the line

Premature end of script headers.

So I tried to execute my test script without cgid, just using perl inside the chroot, and besides some warnings it just worked fine. Here is my script, if its of any interest:

#!/local/perl5/bin/perl
print "Content-type: text/plainnn";
opendir(DIRHANDLE, "/");
@filenames = readdir(DIRHANDLE);
foreach $file (@filenames) { print "$filen"; }
closedir(DIRHANDLE);

(I know its not a great one :))

The warnings were about the locale not being set, so I fixed that by adding /usr/lib/locale to the chroot. This fixed the warnings, but did not fix the original problem. So I assume this was not the root cause. Even more so, when I compared to the 32 bit build, I got the same warnings, however the script would execute fine via cgid.

Next thing I did was to trace the systemcalls via truss -f -o mylogfile.txt. The full output can be found on pastebin (32 bit truss). Here is an excerpt for the 32 bit build (line 4296 on pastebin) – note that paths are not exactly the same as on pastebin, but the observed result is the same:

28420:  sigaction(SIGCLD, 0xFFBFF6A8, 0xFFBFF748)       = 0
28420:  chdir("/path/to/my/chroot/cgi-bin/") = 0
28420:  execve("/path/to/my/chroot/cgi-bin/test.pl", 0x00183DB8, 0x00183570)  argc = 3
28420:      *** SUID: ruid/euid/suid = 50001 / 50001 / 50001  ***
28420:      *** SGID: rgid/egid/sgid = 50001 / 50001 / 50001  ***
28420:  sysinfo(SI_MACHINE, "sun4u", 257)               = 6

And here is the truss output for the 64 bit build. The following is an excerpt (line 4489), note I left out some lines, denoted by [...]:

28906/21:       open("/dev/urandom", O_RDONLY)                  = 12
[...]
28911:  sigaction(SIGCLD, 0xFFFFFFFF7FFFF150, 0xFFFFFFFF7FFFF250) = 0
28911:  chdir("/path/to/my/chroot/cgi-bin/") = 0
28906/21:       pollsys(0xFFFFFFFF747F7080, 1, 0xFFFFFFFF747F6FA0, 0x00000000) = 1
28906/21:       read(12, 0x10034BB38, 8000)                     = 0
28906/21:       close(12)                                       = 0
[...]
28906/21:       read(10, " pEF", 4)                         = 4
28906/21:       kill(28911, SIGTERM)                            Err#3 ESRCH
28904:  close(4)                                        = 0

As Andrew Haenle noticed, I did not execute the same scripts in 32 bit vs 64 bit – at least in the truss output shown above. So here is the truss output for the failing 64 bit, where I execute the same script as in 32 bit: https://pastebin.com/Nz1jBjne

Here is some more truss output from the 64 bit build, with the additional flags -a -e -d: https://pastebin.com/4NMGD2aR

The way I interpret this is that after changing to the cgi-bin directory, cgid gets killed in 64 bit, vs. executing the script in 32 bit.
Permissions are the same, so I do not see what is the problem here. At least it explains the message from the error log – since the script is not executed, no headers are ever printed.

Anyway, I am a bit lost where to go from here. Any hints how to debug this further would be highly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    First of all thank you to all who have made comments and suggestions.

    Finally it turns out that it was a permissions problem. Not in the script, but in the libraries. The way my chroot environment is built is that it gets is custom permissions applied inside the chroot. Now that mechanism was not yet adapted to 64 bit. 64 bit libraries live in different subdirectories of the standard locations for 32 bit backwards compatibility. Also, my httpd process runs as a non-root user. After correcting the permissions perl worked like a charm in 64 bit.

    But maybe more interesting for the general public is how I found this out: I added the -X flag to the apache startup command. That enables debug mode for apache, and finally produced the error message I needed:

    env.pl: Cannot execute /lib/sparcv9/ld.so.1
    cgi-test.cgi: Cannot execute /lib/sparcv9/ld.so.1
    

    After executing - inside the chroot of course -

    chmod o+x /lib/sparcv9/ld.so.1
    chmod o+r /lib/sparcv9/*
    

    my perl test scripts worked again.


  2. Your 32- and 64-bit tests are not the same. Per the posted truss output, the 32-bit process appears to run a Perl CGI script called cgi-test.cgi:

    28415/25:   stat64("/local/content/apache/myinstance.acme.com/cgi-bin/cgi-test.cgi", 0xFAFFBA18) = 0
    28415/25:   lstat64("/local", 0xFAFFBA18)           = 0
    28415/25:   lstat64("/local/content", 0xFAFFBA18)       = 0
    28415/25:   lstat64("/local/content/apache", 0xFAFFBA18)    = 0
    28415/25:   lstat64("/local/content/apache/myinstance.acme.com", 0xFAFFBA18) = 0
    28415/25:   lstat64("/local/content/apache/myinstance.acme.com/cgi-bin", 0xFAFFBA18) = 0
    28415/25:   lstat64("/local/content/apache/myinstance.acme.com/cgi-bin/cgi-test.cgi", 0xFAFFBA18) = 0
    28415/25:   open("/dev/urandom", O_RDONLY)          = 12
    28415/25:   read(12, "C3 E DB1 A03 5 kCBA8DFr".., 64)  = 64
    28415/25:   close(12)                   = 0
    28415/25:   open("/dev/urandom", O_RDONLY)          = 12
    28415/25:   read(12, "E6 L _F3 uBC fA7E18AFC ".., 64)  = 64
    28415/25:   close(12)                   = 0
    28415/25:   so_socket(PF_UNIX, SOCK_STREAM, 0, "", SOV_DEFAULT) = 12
    28415/25:   connect(12, 0xFAFF7AA8, 110, SOV_DEFAULT)  
     ...
    28420:  sigaction(SIGCLD, 0xFFBFF6A8, 0xFFBFF748)   = 0
    28420:  chdir("/local/content/apache/myinstance.acme.com/cgi-bin/") = 0
    28420:  execve("/local/content/apache/myinstance.acme.com/cgi-bin/cgi-test.cgi", 0x00183DB8, 0x00183570)  argc = 3
    28420:      *** SUID: ruid/euid/suid = 50001 / 50001 / 50001  ***
    28420:      *** SGID: rgid/egid/sgid = 50001 / 50001 / 50001  ***
    

    Note that the CGI script is run by PID 28420, where PID 28415 appears to be the “controlling” process.

    But for the 64-bit process, this is the corresponding output, with the CGI script being test.pl:

    28906/21:   stat("/local/content/apache/myinstance.acme.com/cgi-bin/test.pl", 0xFFFFFFFF747FB3E0) = 0
    28906/21:   lstat("/local", 0xFFFFFFFF747FB3E0)     = 0
    28906/21:   lstat("/local/content", 0xFFFFFFFF747FB3E0) = 0
    28906/21:   lstat("/local/content/apache", 0xFFFFFFFF747FB3E0) = 0
    28906/21:   lstat("/local/content/apache/myinstance.acme.com", 0xFFFFFFFF747FB3E0) = 0
    28906/21:   lstat("/local/content/apache/myinstance.acme.com/cgi-bin", 0xFFFFFFFF747FB3E0) = 0
    28906/21:   lstat("/local/content/apache/myinstance.acme.com/cgi-bin/test.pl", 0xFFFFFFFF747FB3E0) = 0
    28906/21:   open("/dev/urandom", O_RDONLY)          = 12
    28906/21:   read(12, "9C `9F9899 uAED9 `1CBE11".., 64)  = 64
    28906/21:   close(12)                   = 0
    28906/21:   open("/dev/urandom", O_RDONLY)          = 12
    28906/21:   read(12, "C2F8FC11C31D = ! V ; O =".., 64)  = 64
    28906/21:   close(12)                   = 0
    28906/21:   so_socket(PF_UNIX, SOCK_STREAM, 0, "", SOV_DEFAULT) = 12
    28906/21:   connect(12, 0xFFFFFFFF747F9560, 110, SOV_DEFAULT) = 0
    ...
    28911:  sigaction(SIGCLD, 0xFFFFFFFF7FFFF150, 0xFFFFFFFF7FFFF250) = 0
    28911:  chdir("/local/content/apache/myinstance.acme.com/cgi-bin/") = 0
    

    Note the lack of an execve() call. And then PID 28911 disappears until this:

    28906/21:   kill(28911, SIGTERM)                Err#3 ESRCH
    28906/21:   kill(28911, SIG#0)              Err#3 ESRCH
    

    There’s not only no execve() call that actually executes the Perl script, there’s no PID 28911 any more.

    The problem appears to be the test.pl script. What are the permissions on the script? What user/group owns it? Does it have any ACLs attached?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search