7.6 Ressourcenlimits eines Prozesses
Wenn ein Prozess an ein bestimmtes Limit stößt, wird in der Regel ein Signal gesendet, oder der Systemaufruf, der versucht, ein Limit zu überschreiten, schlägt fehl. Jeder neu erzeugte oder aufgerufene Prozess erbt seine Limitwerte vom Elternprozess. Dieser Mechanismus wird bereitgestellt, um Prozesse mit gezielten Beschränkungen bezüglich ihres Ressourcenverbrauchs belegen zu können. Diese Limits lassen sich aber auch verändern. Es werden dabei zwei Arten von Limits unterschieden:
|
Soft-Limit – aktueller Wert des Ressourcenlimits eines Prozesses |
|
Hard-Limit – maximaler Wert des Ressourcenlimits eines Prozesses |
Definiert sind diese beiden Limits in der Struktur rlimit, die folgendermaßen aussieht:
struct rlimit {
rlim_t rlim_cur; /* Soft-Limit */
rlim_t rlim_max; /* Hard-Limit */
}
Ist bei der Abfrage der Limits die Konstante RLIM_INFINITY angegeben, so bedeutet dies, dass kein Limit für diese Ressource festgelegt ist. Wenn Sie ein Ressourcenlimit verändern wollen, müssen Sie folgende Regeln beachten:
|
Ein Hard-Limit kann nur von Prozessen mit Superuser-Rechten hochgesetzt werden, egal ob das Limit zuvor reduziert wurde oder nicht. Für das Heruntersetzen sind hingegen keine Superuser-Rechte nötig. |
|
Beim Verändern des Soft-Limits muss der neue Wert immer kleiner oder gleich dem des Hard-Limits sein. |
Ein Ressourcenlimit können Sie mit der Funktion getrlimit() erfragen, verändern können Sie ein Limit mit dem Gegenstück setrlimit(). Hier die Syntax der beiden Funktionen:
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd. h.>
int getrlimit(int ressource, struct rlimit *limit);
int setrlimit(int ressource, const struct rlimit *limit);
Beide Funktionen geben bei Erfolg 0, ansonsten bei einem Fehler ungleich 0 zurück (wie bei so vielen C-Funktionen). Als erstes Argument erwarten diese Funktionen eine entsprechende Ressource, die erfragt bzw. gesetzt werden soll. Das zweite Argument ist ein Zeiger auf die Struktur rlim. Für resource können Sie folgende vordefinierte Konstanten angeben:
Tabelle 7.5
Übersicht der Ressourcenlimits
Ressource
|
Bedeutung
|
vorhanden in …
|
RLIMIT_CPU
|
CPU-Zeit in Millisekunden. Ist das Limit überschritten, wird das Signal SIGXCPU gesendet.
|
SVR4 und BSD
|
RLIMIT_CORE
|
Größe der Core-Datei in Bytes. 0 bedeutet, dass keine Core-Datei angelegt wird.
|
SVR4 und BSD
|
RLIMIT_DATA
|
Größe des gesamten Datensegments (Datensegment, Stack und Heap) in Bytes
|
SVR4 und BSD
|
RLIMIT_FSIZE
|
Max. Größe einer Datei, die beschrieben werden kann. Beim Überschreiten des Soft-Limits wird das Signal SIGXFSZ gesendet.
|
SVR4 und BSD
|
RLIMIT_LOCKS
|
Max. Anzahl Sperren, die mit flock() und fcntl() eingerichtet werden können
|
SVR4, BSD und Linux ab 2.4
|
RLIMIT_MEMLOCK
|
Max. Anzahl der Speicherseiten, die vor einer Auslagerung geschützt werden können
|
Linux und BSD
|
RLIMIT_NOFILE
|
Max. Anzahl von gleichzeitig geöffneten Dateien. Bei BSD ist dies die Konstante RLIMIT_OFILE.
|
SVR4 (und BSD)
|
RLIMIT_NPROC
|
Max. Anzahl von Kindprozessen minus 1 für diesen Prozess
|
BSD
|
RLIMIT_RSS
|
Maximum Resident Set Size (RSS == physikalische Speicherseiten) in KByte. Übersteigt der Prozess dieses Limit, kümmert sich der Kernel darum und nimmt dem Prozess überfälligen Speicher weg.
|
BSD
|
RLIMIT_STACK
|
Max. Stackgröße in Bytes
|
SVR4 und BSD
|
Natürlich gilt auch hier, dass eine Veränderung der Ressourcenlimits nur vom Anfang bis zum Ende der Lebenszeit eines Prozesses gilt. Das folgende Listing demonstriert, wie Sie die aktuellen Ressourcenlimits des aktuell laufenden Prozesses mit getrlimit() abfragen können. Da sich setrlimit() ähnlich anwenden lässt, sollte es kein Problem für Sie sein, diese nachträglich als Übung zu implementieren.
/* my_limit.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
static void limits( int resource ) {
struct rlimit l;
if( getrlimit( resource, &l ) < 0 ) {
printf("keine Angaben\n");
return;
}
printf("Soft-Limit: ");
(l.rlim_cur == RLIM_INFINITY)?
printf("kein Limit "):
printf("%ld ",l.rlim_cur);
printf("Hard-Limit: ");
(l.rlim_max == RLIM_INFINITY)?
printf("kein Limit\n"):
printf("%ld \n",l.rlim_max);
}
int main( void ) {
unsigned int i;
const int limit[] = {
RLIMIT_CPU, RLIMIT_CORE, RLIMIT_DATA, RLIMIT_FSIZE,
/* RLIMIT_LOCKS,*/ RLIMIT_MEMLOCK,
RLIMIT_NOFILE, /* bei BSD RLIMIT_OFILE */
RLIMIT_NPROC, RLIMIT_RSS, RLIMIT_STACK,
};
const char *s_limit[] = {
"RLIMIT_CPU", "RLIMIT_CORE", "RLIMIT_DATA",
"RLIMIT_FSIZE", /* "RLIMIT_LOCKS",*/ "RLIMIT_MEMLOCK",
"RLIMIT_NOFILE", /* bei BSD RLIMIT_OFILE */
"RLIMIT_NPROC", "RLIMIT_RSS", "RLIMIT_STACK",
};
for( i = 0; i< sizeof(limit)/sizeof(long); i++) {
printf("%s = ",s_limit[i]);
limits( limit[i] );
}
return EXIT_SUCCESS;
}
Das Programm bei der Ausführung (hier im Jail einer BSD-Maschine):
$ gcc -o my_limit my_limit.c
$ ./my_limit
RLIMIT_CPU = Soft-Limit:kein Limit Hard-Limit:kein Limit
RLIMIT_CORE = Soft-Limit:kein Limit Hard-Limit:kein Limit
RLIMIT_DATA = Soft-Limit:536870912 Hard-Limit:536870912
RLIMIT_FSIZE = Soft-Limit:kein Limit Hard-Limit:kein Limit
RLIMIT_MEMLOCK= Soft-Limit:kein Limit Hard-Limit:kein Limit
RLIMIT_NOFILE = Soft-Limit:7322 Hard-Limit:7322
RLIMIT_NPROC = Soft-Limit:3661 Hard-Limit:3661
RLIMIT_RSS = Soft-Limit:kein Limit Hard-Limit:kein Limit
RLIMIT_STACK = Soft-Limit:67108864 Hard-Limit:67108864
Wollen Sie hingegen die Ressourcenbenutzung eines Prozesses abfragen, können Sie sich die Funktion getrusage() ansehen, die ebenfalls in der Headerdatei sys/resource.h definiert ist. Die Funktion stammt ursprünglich aus BSD und ist unter Linux noch nicht komplett implementiert. Viele Komponenten geben noch 0 zurück. Mehr dazu entnehmen Sie bitte der Manual Page zu getrusage().
7.6.1 Mehr Sicherheit mit Ressourcenlimits
Ein weiterer positiver Beigeschmack wird Ihnen beim Setzen der Limits gratis mitgeliefert. Z. B. können durch das Limitieren von Filedeskriptoren und der Memorygröße DoS-Attacken (DoS = Denial of Service) eingedämmt werden. Ebenso kann es in einigen Fällen hilfreich sein, die Größe der Core-Files auf 0 zu setzen, wodurch eventuelle Freigaben von vertraulichen Informationen verhindert werden können, wie dies vor ein paar Jahren bei einem FTP-Dämon auf Solaris der Fall war. Hier hatte der FTP-Server eine Datei zur Authentifizierung eines Benutzers in den Speicher geladen. Hacker hatten dann den Prozess durch Signale zum Absturz gebracht, und es wurde eine Core-Datei mit u. a. dem Inhalt der geschützten Daten angelegt, die jetzt munter ausgelesen werden konnten.
|