Dlaczego te bomby typu widelec bash działają inaczej i jakie jest znaczenie & w tym?


16

Rozumiem, jak działa normalna bomba z widelcem, ale tak naprawdę nie rozumiem, dlaczego wymagana jest bomba z widelcem typu bash na końcu i dlaczego te skrypty zachowują się inaczej:

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

i

:(){ : | :& }; :

Ten pierwszy powoduje skok zużycia procesora przed wrzuceniem mnie z powrotem do ekranu logowania. Ten ostatni zamiast tego powoduje zawieszenie się mojego systemu, zmuszając mnie do twardego restartu. Dlaczego? Oba ciągle tworzą nowe procesy, więc dlaczego system zachowuje się inaczej?

Oba skrypty zachowują się inaczej

:(){ : | : }; :

co wcale nie powoduje żadnych problemów, chociaż spodziewałbym się, że będą podobne. Strona podręcznika bash mówi, że polecenia w potoku są już wykonywane w podpowłoce, więc jestem przekonany, że: | : powinno już wystarczyć. Wierzę i powinienem po prostu uruchomić potok w nowej podpowłoce, ale dlaczego to tak bardzo się zmienia?

Edycja: Używając htop i ograniczając liczbę procesów, mogłem zobaczyć, że pierwszy wariant tworzy rzeczywiste drzewo procesów, drugi wariant tworzy wszystkie procesy na tym samym poziomie, a ostatni wariant nie wydaje się tworzyć żadnych procesów w ogóle. To jeszcze bardziej mnie dezorientuje, ale może to jakoś pomaga?


2
myślę, że w twoim ostatnim wariancie brakuje średnika::(){ : | :; }; :
adonis

Odpowiedzi:


22

OSTRZEŻENIE NIE PRÓBUJ URUCHOMIĆ TEGO NA MASZYNIE PRODUKCYJNEJ. TYLKO NIE. Ostrzeżenie: aby wypróbować „bomby”, upewnij się, że ulimit -ujest w użyciu. Przeczytaj poniżej [a] .

Zdefiniujmy funkcję, aby uzyskać PID i datę (czas):

bize:~$ d(){ printf '%7s %07d %s\n' "$1" "$BASHPID" "$(date +'%H:%M:%S')"; }

Prosta, bezproblemowa bombfunkcja dla nowego użytkownika (chroń się: przeczytaj [a] ):

bize:~$ bomb() { d START; echo "yes"; sleep 1; d END; } >&2

Po wywołaniu tej funkcji do wykonania działa ona tak:

bize:~$ bomb
  START 0002786 23:07:34
yes
    END 0002786 23:07:35
bize:~$

Polecenie datejest wykonywane, następnie drukowane jest „tak”, uśpienie przez 1 sekundę, następnie polecenie zamknięcia date, a na koniec funkcja kończy drukowanie nowego wiersza polecenia. Nic fajnego.

| rura

Kiedy wywołujemy funkcję w ten sposób:

bize:~$ bomb | bomb
  START 0003365 23:11:34
yes
  START 0003366 23:11:34
yes
    END 0003365 23:11:35
    END 0003366 23:11:35
bize:~$

Dwa polecenia zaczynają się w pewnym momencie, dwa kończą się 1 sekundę później, a następnie monit powraca.

To jest powód, dla którego rura |rozpoczyna równolegle dwa procesy.

& tło

Jeśli zmienimy połączenie dodając zakończenie &:

bize:~$ bomb | bomb &
[1] 3380
bize:~$
  START 0003379 23:14:14
yes
  START 0003380 23:14:14
yes
    END 0003379 23:14:15
    END 0003380 23:14:15

Monit natychmiast wraca (cała akcja jest wysyłana do tła) i dwa polecenia są wykonywane jak poprzednio. Zwróć uwagę na wartość „numeru zadania” [1]wydrukowanego przed PID procesu 3380. Później ten sam numer zostanie wydrukowany, aby wskazać, że rura się zakończyła:

[1]+  Done                    bomb | bomb

Taki jest efekt &.

Właśnie dlatego &: aby procesy były uruchamiane szybciej.

Prostsza nazwa

Możemy stworzyć funkcję wywoływaną po prostu w bcelu wykonania dwóch poleceń. Wpisany w trzech wierszach:

bize:~$ b(){
> bomb | bomb
> }

I wykonywane jako:

bize:~$ b
  START 0003563 23:21:10
yes
  START 0003564 23:21:10
yes
    END 0003564 23:21:11
    END 0003563 23:21:11

Zauważ, że ;w definicji nie użyliśmy b(nowych linii użyto do oddzielenia elementów). Jednak w przypadku definicji w jednym wierszu zwykle stosuje się ;:

bize:~$ b(){ bomb | bomb ; }

Większość spacji również nie jest obowiązkowa, możemy napisać ekwiwalent (ale mniej wyraźny):

bize:~$ b(){ bomb|bomb;}

Możemy również użyć a, &aby oddzielić }(i wysłać dwa procesy do tła).

Bomba.

Jeśli sprawimy, że funkcja ugryzie się w ogon (nazywając siebie), otrzymamy „bombę widelcową”:

bize:~$ b(){ b|b;}       ### May look better as b(){ b | b ; } but does the same.

Aby przyspieszyć wywoływanie większej liczby funkcji, wyślij potok do tła.

bize:~$ b(){ b|b&}       ### Usually written as b(){ b|b& }

Jeśli dołączymy pierwsze wywołanie do funkcji po wymaganym ;i zmienimy nazwę :, otrzymamy:

bize:~$ :(){ :|:&};:

Zwykle napisane jako :(){ :|:& }; :

Lub, napisany w zabawny sposób, pod jakimś innym imieniem (snow-man):

☃(){ ☃|☃&};☃

Ulimit (który powinieneś ustawić przed uruchomieniem tego) spowoduje, że monit powróci dość szybko po wielu błędach (naciśnij Enter, gdy lista błędów zatrzyma się, aby otrzymać monit).

Powodem tego, że nazywany jest „bombą widełkową”, jest to, że sposób, w jaki powłoka uruchamia podpowłokę, polega na rozwidleniu działającej powłoki, a następnie wywołaniu exec () do rozwidlonego procesu za pomocą polecenia uruchomienia.

Rura „rozwidli” dwa nowe procesy. Robienie tego do nieskończoności powoduje bombę.
Lub królika, jak pierwotnie nazywano, ponieważ rozmnaża się tak szybko.


Wyczucie czasu:

  1. :(){ (:) | (:) }; time :
    Zakończone
    prawdziwe 0m45.627s

  2. :(){ : | :; }; time :
    Zakończone
    prawdziwe 0m15.283s

  3. :(){ : | :& }; time :
    real 0m00.002 s
    Nadal działa


Twoje przykłady:

  1. :(){ (:) | (:) }; :

    Tam, gdzie )oddziela się drugie zamknięcie, }jest to bardziej złożona wersja :(){ :|:;};:. W każdym razie każde polecenie w potoku jest wywoływane wewnątrz podpowłoki. Który jest efektem ().

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

    Jest to szybsza wersja, napisana bez spacji: :(){(:)|:&};:(13 znaków).

  3. :(){ : | : }; : ### działa w Zsh, ale nie w bash.

    Ma błąd składniowy (w bash), metaznak jest potrzebny przed zamknięciem },
    ponieważ:

    :(){ : | :; }; :

[a] Utwórz nowego czystego użytkownika (zadzwonię do mojegobize). Zaloguj się do tego nowego użytkownika w konsoli albosudo -i -u bize:

$ su - bize
Password: 
bize:~$

Sprawdź, a następnie zmień max user processeslimit:

bize:~$ ulimit -a           ### List all limits (I show only `-u`)
max user processes              (-u) 63931
bize:~$ ulimit -u 10        ### Low
bize:~$ ulimit -a
max user processes              (-u) 1000

Przy użyciu tylko 10 działa jako tylko jeden samotny nowy użytkownik: bize. Ułatwia dzwonienie killall -u bizei pozbycie się systemu większości (nie wszystkich) bomb. Proszę nie pytać, które nadal działają, nie powiem. Ale nadal: jest dość niski, ale po bezpiecznej stronie, dostosuj się do swojego systemu .
Zapewni to, że „bomba widełkowa” nie zawali twojego systemu .

Dalsza lektura:

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.