我得到了这个名为 fork.sh 的脚本:
#!/bin/sh
forkbomb() { forkbomb | forkbomb & } ; forkbomb
如果我通过 suexec 调用它,我的整个系统将消耗 99% 的 cpu。为了防止正常的 bash forkbomb,我使用了 limit.conf 并将 nproc 设置为 50。这按预期工作。
但是,如果我通过 httpd 上的 suexec 调用上述脚本,我会看到超过 6000 个任务,系统 cpu 使用率 >97%。我可以看到 user3 fork.sh 的多个条目,cpu 占用率约为 0.6%。如果我调用 systemd-cgtop,system.slice 的 cpu 利用率为 100%,system.slice/httpd.service 的 cpu 利用率为 75%
我用 cgroups 限制了 httpd:
systemctl set-property --runtime httpd.service CPUShares=600 MemoryLimit=500M
我不明白,为什么 ulimits 和 cgroups 不能处理这个问题。
答案1
这些limits
文件由PAM
. apache提供的库存suexec
仍然无法识别或使用PAM
。补丁存在。您可以直接修改源代码来调用setrlimit
(它看起来很简单 - 请参阅setlimit(2)
手册页。)但按原样,suexec
将无法识别您使用limits
.
您仍然可以在 apache 中设置 ulimit,但我认为这是不可取的,特别是在 pre-fork 模型中,因为这样您就限制了 http 服务器可以处理的负载。此外,我不确定限制是否会延续到环境中,suexec
因为我不确定suexec
它是如何发挥作用的。
原因CPUShares
在这里对你没有帮助,因为你的 fork 炸弹是一个资源霸主,但资源并不真正在用户态 CPU 周期中。当涉及 CPU 统计时,为时已晚:您的系统没有可用内存或进程插槽来尝试运行该程序。
您可以尝试prlimit
其中的一部分,util-linux
因此它应该符合您的安装标准。如果你这样做:
$ prlimit --nproc=1 bash -c bash -c id
bash: fork: retry: No child processes
所以这个小小的 2-fork 进程失败了。
不幸的是,我没有看到让 prlimit 参与执行链的合理方法。 Apache 已经把自己和我们所有人都搞砸了,因为它提供了一个已弃用的suexec
模块,该模块不够灵活,无法满足基本需求,而且过于严格,任何真正的解决方案都需要在安全性上炸开一个洞。