Czy linux ma jakieś środki w celu ochrony przed bombami widełkowymi?

12
#include <unistd.h>
int main(int argc, char* argv[]) {
  while(1)
  {
    fork();
  } 
}

Uruchamiam ten program na moim systemie Linux, nic nie wychodzi na terminalu, system operacyjny wydaje się nie działać Czy linux ma jakieś zabezpieczenia dla takiego programu, który może zabraknąć pamięci?


źródło
2
Podejrzewam, że wpływ byłby o wiele mniejszy, gdybyś nie zastosował się do złej rady wielu dystrybutorów, aby stworzyć dużą partycję wymiany ...
R .. GitHub ZATRZYMAJ POMOC W LODZIE
1
Czy „nie tworzenie nowych procesów po uderzeniu 65k” liczy się jako środek zaradczy? ;)
Bobby

Odpowiedzi:

18

Jest to znane jako bomba widełkowa .

Czy linux ma jakieś zabezpieczenia dla takiego programu, który może zabraknąć pamięci?

Nie całkiem. Każdy rozwidlenie wytwarza nowy proces z własną wirtualną przestrzenią adresową i wykorzystaniem pamięci. Każda kopia jest więc stosunkowo mała. W końcu zużyjesz całą pamięć fizyczną + swap w systemie, a zabójca braku pamięci (OOM) zacznie zabijać poszczególne procesy. Ale bomba widelcowa nadal będzie tworzyć procesy równie szybko (jeśli nie szybciej).

Jednym ze sposobów zapobiegania temu jest przede wszystkim ograniczenie liczby procesów użytkownika przy użyciu ulimit -u(zakładając, że używasz Bash; inne powłoki będą miały odpowiedniki).

Oliver Charlesworth
źródło
2
Należy zauważyć, że ulimitjest to specyficzne dla bash; inne powłoki prawdopodobnie będą miały tę samą wbudowaną komendę, ale być może będą miały inną nazwę.
Jay
@Jay: Fair point. Zauważyłem to teraz w odpowiedzi, dzięki!
Oliver Charlesworth,
1
powinno wystarczyć ograniczenie deskryptorów pamięci / plików na użytkownika. Ograniczanie pamięci na użytkownika jest zawsze dobrym pomysłem. Gdy proces zostanie zabity (oom), organ nadzorczy powinien wysłać powiadomienie, aby BOFH mógł uruchomić „nieuczciwego” użytkownika z wszystkimi należącymi do niego procesami poza systemem
Wierzę, że możesz również ustawić pewne ograniczenia za pomocą parametrów logowania
p_l
10

Tak, chociaż może nie być domyślnie włączony w twoim systemie. setrlimitPołączenie systemu określa granice systemu - liczbę procesów na użytkownika.

Najpierw spójrzmy na to w interfejsie API jądra (ponieważ wspomniałeś o „linux”): możesz użyć manpage dla setrlimit, który powie ci, żebyś zrobił coś takiego

#include <sys/resource.h>
...

struct rlimit  r;

rnew.r_cur = 40;
rnew.r_max = 50;
setrlimit(RLIMIT_NPROC,&r);

Spowoduje to ustawienie maksymalnej liczby procesów na użytkownika ( RLIMIT_NPROC) na 40 (miękki limit) i 50 (twardy limit).

Teraz z powłoki, jeśli używasz bash, możesz użyć ulimitwbudowanego polecenia:

ulimit -u
29089

Możesz ustawić limit, przekazując go jako argument:

ulimit -u 100

ulimit --help pokaże Ci, że istnieje kilka innych limitów, które możesz ustawić (jednym z nich może być maksymalna liczba deskryptorów plików używanych przez użytkownika).

Sójka
źródło
7

To zależy, czy chcesz go używać na poziomie użytkownika czy systemu. Na poziomie użytkownika ulimit(lub odpowiednie polecenia dla innych powłok) byłoby najłatwiejszym rozwiązaniem.

Jednak na poziomie systemu istnieją mechanizmy zapobiegające zatrzymaniu systemu przez złośliwych użytkowników (lub po prostu nieużywających ulimit). Mechanizm cgroups w systemie Linux może ograniczać zasoby dla poszczególnych grup. Możesz zmusić ( pam_systemdmachanizmem), aby sesja użytkownika była w określonej grupie. Ma to inne zalety, na przykład dla harmonogramu procesora.

Maciej Piechotka
źródło
1
+1: grupy są naprawdę nowe i większość ludzi jeszcze o nich niewiele wie. Gdzie możemy dowiedzieć się więcej?
Ken Bloom
1
@KenBloom: 1. przeglądając /sys/fs/cgroup/2. wyszukując w Google 3. przeglądając make menuconfig4. przeglądając /usr/src/linux/Documentation/cgroups5. przeglądając dokumentację systemową. Przepraszam, nie mogę pomóc, ale wykorzystałem tylko te zasoby. Użyłem cgroups na pulpicie do kontrolowania zasobów.
Maciej Piechotka,
6

Użyj ulimit -uz powłoki bash, aby ustawić limit „maksymalnych procesów użytkownika”.

Z powłoki C używasz limitpolecenia.

Jeśli potrzebujesz do tego wywołania systemowego, użyj setrlimitpołączenia, aby ustawić RLIMIT_NPROC.

Ken Bloom
źródło