Por que não posso travar meu sistema com uma bifurcação?

52

Recentemente eu tenho desenterrado informações sobre processos no GNU / Linux e conheci a infame bomba:

:(){ : | :& }; :

Teoricamente, é suposto duplicar-se infinitamente até o sistema ficar sem recursos ...

No entanto, eu tentei testar ambos em uma CLI Debian e em uma distro GUI Mint , e isso não parece impactar muito o sistema. Sim, existem toneladas de processos que são criados e depois de um tempo eu li em mensagens de console como:

bash: fork: Resource temporarily unavailable

bash: fork: retry: No child processes

Mas depois de algum tempo, todos os processos são mortos e tudo volta ao normal. Eu li que o ulimit definiu uma quantidade máxima de processos por usuário, mas parece que não consigo elevá-lo muito.

Quais são as proteções do sistema contra uma fork-bomb? Por que não se replica até que tudo congele ou pelo menos fique muito atrasado? Existe uma maneira de realmente travar um sistema com uma bifurcação?

    
por Plancton 19.09.2018 / 09:32

3 respostas

85

Você provavelmente tem uma distro Linux que usa o systemd.

O Systemd cria um cgroup para cada usuário, e todos os processos de um usuário pertencem ao mesmo cgroup.

Cgroups é um mecanismo do Linux para definir limites em recursos do sistema como número máximo de processos, ciclos de CPU, uso de RAM, etc. Esta é uma camada diferente e mais moderna de limitação de recursos que ulimit (que usa getrlimit() syscall).

Se você executar systemctl status user-<uid>.slice (que representa o cgroup do usuário), poderá ver o número atual e máximo de tarefas (processos e encadeamentos) permitidos dentro desse cgroup.

$ systemctl status user-$UID.slice
● user-22001.slice - User Slice of UID 22001
   Loaded: loaded
  Drop-In: /usr/lib/systemd/system/user-.slice.d
           └─10-defaults.conf
   Active: active since Mon 2018-09-10 17:36:35 EEST; 1 weeks 3 days ago
    Tasks: 17 (limit: 10267)
   Memory: 616.7M

Por padrão, o número máximo de tarefas que o systemd permitirá para cada usuário é de 33% do "máximo do sistema" ( sysctl kernel.threads-max ); Isso geralmente equivale a ~ 10.000 tarefas. Se você quiser alterar este limite:

  • No systemd v239 e posterior, o padrão do usuário é definido via TasksMax = em:

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

    Para ajustar o limite para um usuário específico (que será aplicado imediatamente, assim como armazenado em /etc/systemd/system.control), execute:

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

    Os mecanismos usuais de sobrescrever as configurações de uma unidade (como systemctl edit ) podem ser usados aqui também, mas eles exigirão uma reinicialização. Por exemplo, se você quiser alterar o limite para cada usuário, poderá criar /etc/systemd/system/user-.slice.d/15-limits.conf .

  • No systemd v238 e anterior, o padrão do usuário é definido por UserTasksMax = em /etc/systemd/logind.conf . Alterar o valor geralmente requer uma reinicialização.

Mais informações sobre isso:

por 19.09.2018 / 10:46
12

Isso não trará mais problemas nos sistemas Linux modernos.

Cria hordas de processos, mas não queima muito a CPU, pois os processos ficam ociosos. Você fica sem slots na tabela de processos antes de ficar sem RAM agora.

Se você não é cgroup limitado como Hkoof aponta, a seguinte alteração ainda traz os sistemas para baixo:

:(){ : | :& : | :& }; :
    
por 19.09.2018 / 18:25
8

De volta aos anos 90 eu acidentalmente soltei um desses em mim mesmo. Eu tinha definido inadvertidamente o bit de execução em um arquivo de origem C que tinha um comando fork () nele. Quando eu cliquei duas vezes nele, o csh tentou executá-lo em vez de abri-lo em um editor como eu queria.

Mesmo assim, não travou o sistema. O Unix é robusto o suficiente para que sua conta e / ou sistema operacional tenham um limite de processo. O que acontece, em vez disso, é que ele fica super lento e qualquer coisa que precise iniciar um processo provavelmente falhará.

O que acontece nos bastidores é que a tabela de processos é preenchida com processos que estão tentando criar novos processos. Se um deles terminar (devido a um erro na bifurcação porque a tabela de processos está cheia ou devido a um operador desesperado tentando restaurar a sanidade em seu sistema), um dos outros processos manipulará um novo para preencher. o vazio.

A "fork fork" é basicamente um sistema de processos auto-reparador involuntário em uma missão para manter sua tabela de processos completa. A única maneira de parar é matá-los de uma vez.

    
por 19.09.2018 / 20:30