为什么我不能用叉子炸弹让我的系统崩溃?

为什么我不能用叉子炸弹让我的系统崩溃?

最近我一直在挖掘有关 GNU/Linux 进程的信息,并且遇到了臭名昭著的 fork 炸弹:

:(){ : | :& }; :

理论上,它应该无限复制自己,直到系统耗尽资源......

但是,我尝试过在命令行界面和一个桂薄荷发行版,它似乎对系统影响不大。是的,创建了大量进程,过了一会儿我在控制台消息中读到,例如:

bash:fork:资源暂时不可用

bash:fork:重试:没有子进程

但一段时间后,所有进程都会被终止,一切都会恢复正常。我读过极限值设置每个用户的最大进程量,但我似乎无法将其提高太多。

针对叉子炸弹的系统保护措施有哪些?为什么它不自我复制,直到一切都冻结或至少滞后很多?有没有办法真正用叉子炸弹让系统崩溃?

答案1

您可能有一个使用 systemd 的 Linux 发行版。

Systemd为每个用户创建一个cgroup,一个用户的所有进程都属于同一个cgroup。

Cgroups 是一种 Linux 机制,用于设置系统资源限制,例如最大进程数、CPU 周期、RAM 使用情况等。这是一个与ulimit(使用getrlimit()系统调用)不同的、更现代的资源限制层。

如果运行systemctl status user-<uid>.slice(代表用户的cgroup),可以看到当前和最大数量任务该 cgroup 中允许的(进程和线程)。

$ systemctl status user-$UID.slice
● user-22001.slice - UID 22001 的用户切片
   已加载:已加载
  插入:/usr/lib/systemd/system/user-.slice.d
           └─10-defaults.conf
   活跃:自东部夏令时间 2018-09-10 星期一 17:36:35 起活跃; 1 周 3 天前
    任务:17(限制:10267)
   内存:616.7M

默认情况下,systemd 允许每个用户执行的最大任务数是“系统范围最大任务数”的 33% ( sysctl kernel.threads-max);这通常相当于约 10,000 个任务。如果您想更改此限制:

  • 在 systemd v239 及更高版本中,用户默认设置是通过最大任务数=在:

    /usr/lib/systemd/system/user-.slice.d/10-defaults.conf
    

    要调整特定用户的限制(将立即应用并存储在 /etc/systemd/system.control 中),请运行:

    systemctl [--runtime] set-property user-<uid>.slice TasksMax=<value>
    

    此处也可以使用覆盖设备设置的常用机制(例如systemctl edit),但需要重新启动。例如,如果您想更改以下限制每一个用户,您可以创建/etc/systemd/system/user-.slice.d/15-limits.conf.

  • 在 systemd v238 及更早版本中,用户默认设置是通过用户任务最大=/etc/systemd/logind.conf。更改该值通常需要重新启动。

有关此的更多信息:

答案2

无论如何,这不会再使现代 Linux 系统崩溃。

它会创建大量进程,但当进程空闲时并不会真正消耗那么多 CPU。现在,在用完 RAM 之前,您已经用完了进程表中的插槽。

如果您没有像 Hkoof 指出的那样限制 cgroup,则以下更改仍然会导致系统崩溃:

:(){ : | :& : | :& }; :

答案3

早在 90 年代,我就无意中向自己释放了其中一个。我无意中在包含 fork() 命令的 C 源文件上设置了执行位。当我双击它时,csh 尝试运行它,而不是像我想要的那样在编辑器中打开它。

即使如此,它也没有使系统崩溃。 Unix 足够强大,您的帐户和/或操作系统将有进程限制。相反,它会变得非常缓慢,任何需要启动进程的事情都可能会失败。

幕后发生的事情是进程表填满了试图创建新进程的进程。如果其中一个进程终止(由于进程表已满而导致分叉错误,或者由于绝望的操作员试图恢复系统的正常状态),其他进程之一将愉快地分叉一个新进程来填充虚空。

“叉子炸弹”基本上是一个无意的进程自我修复系统,其任务是保持进程表满。阻止它的唯一方法就是以某种方式一次性杀死他们。

相关内容