在 solaris 上通过 cgid 执行 perl 在 64 位中失败,但在 32 位中工作



我有一个自定义构建的 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 -dhttps://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测试脚本再次工作。

相关内容

最新更新