我有一个自定义构建的 apachehttpd
版本 2.2 和 Solaris 10 上的perl
版本 5.22。httpd 在 chroot 环境中运行,perl 脚本通过 httpd 的mod_cgid
执行。到目前为止,一切都在 32 位中工作。现在我已经用 64 位编译了所有内容(因为另一个 httpd 模块仅作为 64 位二进制文件提供(,现在我无法通过 cgid 执行 perl 脚本。
http 错误日志包含以下行
Premature end of script headers.
所以我尝试在没有 cgid 的情况下执行我的测试脚本,只是在 chroot 中使用 perl,除了一些警告之外,它工作正常。这是我的脚本,如果它有任何兴趣:
#!/local/perl5/bin/perl
print "Content-type: text/plainnn";
opendir(DIRHANDLE, "/");
@filenames = readdir(DIRHANDLE);
foreach $file (@filenames) { print "$filen"; }
closedir(DIRHANDLE);
(我知道这不是一个好:)(
警告是关于未设置区域设置的,因此我通过将/usr/lib/locale
添加到 chroot 来修复它。这修复了警告,但没有解决原始问题。所以我认为这不是根本原因。更重要的是,当我与 32 位构建相比时,我收到了相同的警告,但是脚本可以通过 cgid 执行正常。
我做的下一件事是通过truss -f -o mylogfile.txt
跟踪系统调用。完整的输出可以在 pastebin (32 位桁架(上找到。以下是32位构建的摘录(粘贴上的第 4296 行( - 请注意,路径与 pastebin 上的路径不完全相同,但观察到的结果是相同的:
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
这是64位构建的桁架输出。以下是摘录(第 4489 行(,请注意我省略了一些行,用[...]
表示:
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
正如 Andrew Haenle 所注意到的,我没有在 32 位和 64 位中执行相同的脚本 - 至少在上面显示的桁架输出中。所以这里是失败的 64 位的桁架输出,我在其中执行与 32 位相同的脚本:https://pastebin.com/Nz1jBjne
以下是来自64位构建的更多桁架输出,附加标志-a -e -d
https://pastebin.com/4NMGD2aR:
我的解释是,在更改为 cgi-bin 目录后,cgid 在 64 位中被杀死,而不是以 32 位执行脚本。 权限是相同的,所以我看不出这里有什么问题。至少它解释了错误日志中的消息 - 由于脚本未执行,因此不会打印任何标头。
无论如何,我有点迷茫,从这里开始。任何有关如何进一步调试的提示将不胜感激。
您的 32 位和 64 位测试是不一样的。 根据发布的truss
输出,32位进程似乎运行一个名为cgi-test.cgi
的Perl 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 ***
请注意,CGI 脚本由 PID 28420 运行,其中 PID 28415 似乎是"控制"进程。
但是对于 64 位进程,这是相应的输出,CGI 脚本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
请注意缺少execve()
调用。 然后 PID 28911 消失,直到这样:
28906/21: kill(28911, SIGTERM) Err#3 ESRCH
28906/21: kill(28911, SIG#0) Err#3 ESRCH
不仅没有实际执行 Perl 脚本的execve()
调用,也不再有 PID 28911。
问题似乎是脚本test.pl
。 脚本的权限是什么? 哪个用户/组拥有它? 它是否附加了任何 ACL?
首先感谢所有提出意见和建议的人。
最后事实证明这是一个权限问题。不是在脚本中,而是在库中。我的 chroot 环境的构建方式是它获得在 chroot 内部应用的自定义权限。现在该机制尚未适应 64 位。64 位库位于标准位置的不同子目录中,以实现 32 位向后兼容性。此外,我的httpd进程以非root用户身份运行。更正权限后,perl 在 64 位中就像一个魅力。
但对于公众来说,也许更有趣的是我是如何发现这一点的:我将-X
标志添加到 apache 启动命令中。这为 apache 启用了调试模式,并最终产生了我需要的错误消息:
env.pl: Cannot execute /lib/sparcv9/ld.so.1
cgi-test.cgi: Cannot execute /lib/sparcv9/ld.so.1
执行后 - 当然是在 chroot 内部 -
chmod o+x /lib/sparcv9/ld.so.1
chmod o+r /lib/sparcv9/*
我的Perl测试脚本再次工作。