1. 27
  1.  

  2. 4

    This is also extremely useful and effective in case you have to deal with a fork bomb: SIGSTOP its process tree to make the processes stop spawning new children, then SIGKILL them all at once.

    1. 5

      It is probably enough to stop naive fork bombs, but it’s not safe against truly adversarial input. You can write a fork bomb to escape this technique.

      I’m not sure what set of processes the systemd code is trying to kill. But there is a fundamental race condition between:

      1. List all the processes matching <some property> (i.e. they might be descendants of a shell that started a fork bomb, etc.)
      2. Kill all those processes, or send SIGSTOP to them

      The problem is that between steps 1 and 2, any of those processes can fork(). They can spawn children to escape your wrath :) Even with SIGSTOP, you still have the problem of determining which of them match the property.

      There is no solution to this problem in POSIX – processes aren’t treated as adversarial in this regard. On Linux, the solution is the freezer cgroup. There’s no way for a process to “escape” a cgroup.

      Again I’m not clear on the context of the code, but my understanding is that systemd uses cgroups all over the place, so I’m not sure why they wouldn’t use it for killing processes.

      I guess it’s “late stage shutdown” when the computer is shutting off? That technique is probably fine then since shutting off is a very special operation, where you don’t need to preserve any invariants of the system after that operation.

      But if you want to try to write a stable cluster manager (as I once tried), you should treat processes as adversarial and use cgroups (on Linux).

      https://github.com/torvalds/linux/blob/master/Documentation/cgroup-v1/freezer-subsystem.txt

      It’s not a trivial problem, I bookmarked this awhile ago:

      https://issues.apache.org/jira/browse/MESOS-1689

      EDIT: If the fork bomb is started under a non-root user, I believe you can just kill all the processes under the UID with the given technique. The process shouldn’t be able to escape that property by forking (without privilege escalation). But that’s the best you can do – there’s no way to reliably kill a fork bomb while leaving other processes under the same UID untouched.