Questa mattina ho letto un post che descrive una apparente vulnerabilità dei sistemi Linux. Si tratta in realtà di una sequenza di caratteri che – se lanciata da linea di comando – genera un loop infinito, con conseguente blocco di CPU e saturazione di RAM. Non si tratta quindi di una deficienza di Linux, ma di un evidente errore logico di chi lancia la stringa da bash su qualsiasi sistema operativo che ne sia dotato. L’autore del post suggerisce comunque la soluzione più semplice ed efficace per ovviare agli effetti del microscopico ma pericoloso script.
Forse questo articolo può essere utile per smorzare un po’ i toni apologetici con cui si decanta l’inossidabile sistema operativo GNU/Linux: esiste infatti una sequenza di pochi caratteri che, se digitata nel terminale, manda l’intero sistema in tilt. Ecco a voi il codice incriminato:
: () { : | : & };:
Com’è possibile che questa breve ed enigmatica stringa possa creare tanto scompiglio? In realtà ciò che succede è abbastanza normale e la spiegazione, per chi ha un’alfabetizzazione di bash script, è la seguente: le funzioni in bash.
Le funzioni, in bash, vengono dichiarate con la sintassi:
nomeFunzione() { comando1; comando2; ... comandoN; }
e vengono invocate scrivendo il loro nome, come dei normali comandi. Quindi, ad esempio, il seguente codice:
saluta(){ echo "ciao"; };saluta
non fa che dichiarare la funzione saluta, la quale stampa sul terminale la parola ciao, ed invocarla. Nel codice incriminato la funzione si chiamava : (due punti).
Ebbene sì: nonostante sia particolarmente esotico è un nome legale per una funzione bash.
Come si potrà osservare ora, alla luce di quanto detto, la funzione (una volta invocata) richiama se stessa e reindirizza il proprio output in un’altra invocazione di se stessa tramite la pipe (barra verticale). Se non conoscete le pipe, su cui non è il caso di soffermarsi approfonditamente ai fini della spiegazione (e su cui si trova ampia documentazione in giro), basti sapere che hanno l’effetto di aprire in parallelo i due comandi tra cui compaiono; quindi il codice : | : che figura nel corpo della funzione invocherà due volte e parallelamente la funzione stessa, dando vita ad una (doppia) ricorsione.
In ultimo, la & posta alla fine del comando ha l’effetto di eseguirlo in background.
Dunque: quando la funzione viene lanciata, invoca se stessa due volte in parallelo creando quindi una biforcazione (fork), ognuna delle due biforcazioni si sdoppia a sua volta, e via discorrendo. Il fatto che le funzioni vengano lanciate in background garantisce che terminandone una (ad esempio con il comando kill), quelle da lei create (quindi le due biforcazioni e le loro discendenti) non verranno terminate a loro volta come avverrebbe normalmente. Questo inarrestabile avvio di funzioni, che procede esponenzialmente, finisce per saturare le risorse (CPU e memoria) e dopo un po’ di tempo sopraggiunge il congelamento del sistema.
L’antidoto. Per i più timorosi: l’antidoto per queste fork bomb esiste e consiste semplicemente nel porre un limite al numero di processi avviabili da un utente.
Post originale:
https://www.tuxbay.org/index.php?option=com_content&task=view&id=152&Itemid=1