Recientemente estuve desenterrando información sobre procesos en GNU / Linux y conocí la infame bomba tenedor:
:(){ : | :& }; :
Teóricamente, se supone que se duplicará infinitamente hasta que el sistema se quede sin recursos ...
Sin embargo, he intentado probar tanto en una distribución CLI Debian como en una distribución GUI Mint , y no parece afectar mucho al sistema. Sí, hay toneladas de procesos que se crean, y después de un tiempo leí en la consola mensajes como:
bash: fork: recurso temporalmente no disponible
bash: fork: retry: no hay procesos secundarios
Pero después de un tiempo, todos los procesos simplemente se anulan y todo vuelve a la normalidad. He leído que el ulimit establece una cantidad máxima de proceso por usuario, pero parece que no puedo llegar muy lejos.
¿Cuáles son las protecciones del sistema contra una bomba tenedor? ¿Por qué no se replica hasta que todo se congela o al menos se retrasa mucho? ¿Hay alguna manera de bloquear realmente un sistema con una bomba tenedor?
:(){ :& :; }; :
lugar? ¿También terminan siendo asesinados todos eventualmente? ¿Qué hay de:(){ while :& do :& done; }; :
?Respuestas:
Probablemente tenga una distribución de Linux que use systemd.
Systemd crea un cgroup para cada usuario, y todos los procesos de un usuario pertenecen al mismo cgroup.
Cgroups es un mecanismo de Linux para establecer límites en los recursos del sistema, como el número máximo de procesos, ciclos de CPU, uso de RAM, etc. Esta es una capa diferente, más moderna, de limitación de recursos que
ulimit
(que utiliza lagetrlimit()
llamada al sistema).Si ejecuta
systemctl status user-<uid>.slice
(que representa el cgroup del usuario), puede ver el número actual y máximo de tareas (procesos y subprocesos) permitidas dentro de ese cgroup.Por defecto, el número máximo de tareas que systemd permitirá para cada usuario es el 33% del "máximo de todo el sistema" (
sysctl kernel.threads-max
); esto generalmente equivale a ~ 10,000 tareas. Si desea cambiar este límite:En systemd v239 y posterior, el valor predeterminado del usuario se establece a través de TasksMax = en:
Para ajustar el límite para un usuario específico (que se aplicará inmediatamente y se almacenará en /etc/systemd/system.control), ejecute:
Los mecanismos habituales para anular la configuración de una unidad (como
systemctl edit
) también se pueden usar aquí, pero requerirán un reinicio. Por ejemplo, si desea cambiar el límite para cada usuario, puede crear/etc/systemd/system/user-.slice.d/15-limits.conf
.En systemd v238 y versiones anteriores, el valor predeterminado del usuario se establece a través de UserTasksMax = in
/etc/systemd/logind.conf
. Cambiar el valor generalmente requiere un reinicio.Más información sobre esto:
fuente
De todos modos, esto ya no bloqueará los sistemas Linux modernos.
Crea acumulaciones de procesos, pero en realidad no quema tanta CPU a medida que los procesos permanecen inactivos. Usted se queda sin ranuras en la tabla de procesos antes de quedarse sin RAM ahora.
Si no está limitado a cgroup como lo señala Hkoof, la siguiente alteración aún hace que los sistemas se caigan:
fuente
fork
una y otra vez), y el resto de su tiempo haciendo la llamada a la función (usando cada vez más memoria para cada llamada en la pila de llamadas del shell, presumiblemente).:(){ :& :; }; :
lugar de la de la pregunta. Realmente no he pensado completamente en el flujo de ejecución del arquetípico como se da.En los años 90, accidentalmente solté uno de estos en mí. Inadvertidamente configuré el bit de ejecución en un archivo fuente C que tenía un comando fork (). Cuando hice doble clic en él, csh intentó ejecutarlo en lugar de abrirlo en un editor como quería.
Incluso entonces, no bloqueó el sistema. Unix es lo suficientemente robusto como para que su cuenta y / o el sistema operativo tengan un límite de proceso. En cambio, lo que sucede es que se vuelve muy lento y es probable que falle todo lo que necesite para iniciar un proceso.
Lo que sucede detrás de escena es que la tabla de procesos se llena con procesos que intentan crear nuevos procesos. Si uno de ellos finaliza (ya sea debido a un error en la bifurcación porque la tabla de procesos está llena o debido a un operador desesperado que intenta restaurar la cordura en su sistema), uno de los otros procesos bifurcará alegremente uno nuevo para llenar el vacío.
La "bomba tenedor" es básicamente un sistema de procesos que se repara a sí mismo involuntariamente en una misión para mantener su mesa de procesos llena. La única forma de detenerlo es matarlos de alguna manera a la vez.
fuente
-1
no es una bandera.kill
solo toma una opción y luego detiene las opciones de análisis. Esto mata la identificación del proceso-1
, que es un alias para todos los procesos.