Provided by: manpages-de-dev_4.21.0-2_all bug

BEZEICHNUNG

       execve - Programm ausführen

BIBLIOTHEK

       Standard-C-Bibliothek (libc, -lc)

ÜBERSICHT

       #include <unistd.h>

       int execve(const char *Pfadname, char *const _Nullable argv[],
                  char *const _Nullable envp[]);

BESCHREIBUNG

       execve()  führt das Programm aus, auf das sich Pfadname bezieht. Dies führt dazu, dass das
       Programm, das derzeit vom aufrufenden Prozess ausgeführt wird, durch ein  neues  Programm,
       mit  einem  frisch initialisierten Stack, Heap und (initialisierten und uninitialisierten)
       Datensegmenten ersetzt wird.

       Pfadname muss entweder ein binäres ausführbares Programm oder ein  Skript  sein,  das  mit
       einer Zeile der folgenden Form beginnt:

           #!Interpreter [Optionale-Arg]

       Einzelheiten zu letzterem Fall finden Sie in »Interpreter-Skripte« weiter unten.

       argv  ist  ein  Feld  von  Zeigern  auf Zeichenketten, die an das neue Programm als dessen
       Befehlszeilenargumente  übergeben  werden.  Per  Konvention  sollte   die   erste   dieser
       Zeichenketten  (d.h.  argv[0])  den  Dateinnamen,  der  zu  der ausgeführten Datei gehört,
       enthalten. Das Feld argv muss durch einen NULL-Zeiger beendet werden. (Daher wird  in  dem
       neuen Programm argv[argc] NULL sein.)

       envp  ist  ein Feld von Zeigern auf Zeichenketten, gewöhnlich von der Form Schlüssel=Wert,
       die an die Umgebung des neuen Programms übergeben werden. Das Feld envp muss  durch  einen
       NULL-Zeiger beendet werden.

       Diese  Handbuchseite beschreibt den Linux-Systemaufruf im Detail; für einen Überblick über
       die Nomenklatur  und  die  vielen,  oft  zu  bevorzugenden,  durch  Libc  bereitgestellten
       Varianten dieser Funktion, einschließlich der, die die Umgebungsvariable PATH durchsuchen,
       siehe exec(3).

       Auf den Argumentzeiger und die Umgebung kann von der  Main-Funktion  des  neuen  Programms
       zugegriffen werden, wenn sie wie folgt definiert ist:

           int main(int argc, char *argv[], char *envp[])

       Beachten Sie allerdings, dass die Verwendung eines dritten Arguments bei der Funktion main
       nicht in POSIX.1 spezifiziert ist; laut POSIX.1 sollte auf die Umgebung über  die  externe
       Variable environ(7) zugegriffen werden.

       execve()  kehrt  bei  Erfolg nicht zurück und Text, initialisierte Daten, uninitialisierte
       Daten (bss) und Stack des aufrufenden Prozesses werden entsprechend des  Inhalts  des  neu
       geladenen Programms überschrieben.

       Falls  das  aktuelle  Programm  mit  ptrace  verfolgt  wird, wird nach einem erfolgreichen
       execve() ein Signal SIGTRAP an es gesandt.

       Falls bei der Programmdatei, auf die sich Pfadname bezieht, das  Bit  set-user-ID  gesetzt
       ist,  dann  wird  die  effektive  Benutzerkennung  des  aufrufenden  Programms  zu der des
       Eigentümers der Programmdatei geändert. Ähnlich  wird  die  effektive  Gruppenkennung  des
       aufrufenden  Prozesses auf die Gruppe der Programmdatei gesetzt, wenn das Bit set-group-ID
       auf der Programmdatei gesetzt ist.

       Die vorgenannten Umwandlungen der effektiven Kennungen werden nicht durchgeführt (d.h. die
       Bits  set-user-ID  und  set-group-ID  werden ignoriert), falls eine der folgenden Aussagen
       wahr ist:

       •  Das Attribut no_new_privs wird für den aufrufenden Thread gesetzt (siehe prctl(2)).

       •  Das unterliegende  Dateisystem  ist  nosuid  eingehängt  (der  Schalter  MS_NOSUID  für
          mount(2)).

       •  Der aufrufende Prozess wird mit ptrace verfolgt.

       Die  Capabilities  der  Programmdatei  (siehe capabilities(7)) werden auch ignoriert, wenn
       eine der obigen Bedingungen zutrifft.

       Die effektive Benutzerkennung des Prozesses wird in die gespeicherte set-user-ID  kopiert.
       Ähnlich wird die effektive Gruppenkennung in die gespeicherte set-group-ID kopiert. Dieses
       Kopieren findet nach allen effektiven ID-Änderungen  statt,  die  aufgrund  der  Modusbits
       set-user-ID und set-group-ID erfolgen.

       Die  reale  UID und reale GID des Prozesses sowie die zusätzlichen Gruppenkennungen ändern
       sich beim Aufruf von execve() nicht.

       Falls das  Programm  eine  dynamisch  gelinkte  Programmdatei  im  a.out-Format  ist,  die
       dynamische  Bibliotheken-Stubs enthält, dann wird der dynamische Linker ld.so(8) von Linux
       am Anfang der Ausführung aufgerufen, um die benötigten Laufzeitobjekte in den Speicher  zu
       bringen und das Programm mit ihnen zu verlinken.

       Falls  das  Programm  ein  dynamisch  gelinktes  ELF-Programm ist, wird der in dem Segment
       PT_INTERP  benannte  Interpreter  zum  Laden  der  gemeinsamen  Objekte  verwandt.  Dieser
       Interpreter ist typischerweise /lib/ld-linux.so.2 für Programme, die mit der Glibc gelinkt
       sind (siehe ld-linux.so(8)).

   Auswirkung auf Prozessattribute
       Alle außer den  nachfolgend  aufgeführten  Prozessattributen  werden  durch  ein  execve()
       erhalten:

       •  Die Zuordnung aller gefangenen Signale wird auf die Vorgabe zurückgesetzt (signal(7)).

       •  Alle alternativen Signal-Stacks werden nicht erhalten (sigaltstack(2)).

       •  Speicher-Mappings werden nicht erhalten (mmap(2)).

       •  Gemeinsam benutzte Speichersegmente vom Typ »System V« werden abgetrennt (shmat(2)).

       •  Mappings gemeinsamer Speicherbereiche gemäß POSIX werden aufgehoben (shm_open(3)).

       •  Offene POSIX-Nachrichtenwarteschlangendeskriptoren werden geschlossen (mq_overview(7)).

       •  Alle offenen benannten POSIX-Semaphoren werden geschlossen (sem_overview(7)).

       •  POSIX-Timer werden nicht erhalten (timer_create(2)).

       •  Alle offenen Verzeichnis-Streams werden geschlossen (opendir(3)).

       •  Speichersperren werden nicht erhalten (mlock(2), mlockall(2)).

       •  Exit-Handler werden nicht erhalten (atexit(3), on_exit(3)).

       •  Die Gleitkomma-Umgebung wird auf den Standardwert zurückgesetzt (siehe fenv(3)).

       Die  Prozessattribute  in  der  vorstehenden  Liste sind alle in POSIX.1 spezifiziert. Die
       folgenden Linux-spezifischen Prozessattribute werden auch  während  eines  execve()  nicht
       erhalten:

       •  Das Attribut »dumpable« ist auf den Wert 1 gesetzt, außer ein set-user-ID-Programm, ein
          set-group-ID-Programm oder ein Programm mit Capabilitys  wird  ausgeführt,  in  welchem
          Fall  der  »dumpable«-Schalter  stattdessen  unter  den  in PR_SET_DUMPABLE in prctl(2)
          beschriebenen Umständen auf den Wert in /proc/sys/fs/suid_dumpable zurückgesetzt werden
          kann.   Beachten  Sie,  dass  Änderungen  am  Attribut  »dumpable«  zu  Änderungen  der
          Eigentümerschaft von Dateien im  Verzeichnis  /proc/PID  des  Prozesses  auf  root:root
          führen können, wie dies in proc(5) beschrieben ist.

       •  Der prctl(2)-Schalter PR_SET_KEEPCAPS wird auf 0 gesetzt.

       •  (Seit  Linux  2.4.36  /  2.6.23)  Falls  ein  set-user-ID-  oder  set-group-ID-Programm
          ausgeführt wird, dann wird das durch den Schalter  prctl(2)  PR_SET_PDEATHSIG  gesetzte
          Todessignal des Elternprozesses auf 0 gesetzt.

       •  Der  Prozessname,  wie  er  von  prctl(2)  PR_SET_NAME  gesetzt  (und  durch ps -o comm
          angezeigt) wird, wird auf den Namen des ausführbaren Programms zurückgesetzt.

       •  Der SECBIT_KEEP_CAPS Schalter securebits wird auf 0 gesetzt. Siehe capabilities(7).

       •  Das Terminierungssignal wird auf SIGCHLD zurückgesetzt (siehe clone(2)).

       •  Die Dateideskriptortabelle wird getrennt, der  Effekt  des  Schalters  CLONE_FILES  von
          clone(2) wird rückgängig gemacht.

       Beachten Sie die folgenden weiteren Punkte:

       •  Alle  Threads  außer  dem  aufrufenden  werden während eines execve() zerstört. Mutexe,
          Bedingungsvariablen und andere Pthread-Objekte werden nicht erhalten.

       •  Das Äquivalent von setlocale(LC_ALL, "C") wird beim Programmstart ausgeführt.

       •  POSIX.1 legt fest,  dass  Zuordnungen  aller  ignorierten  oder  auf  die  Vorgabewerte
          gesetzten  Signale  unverändert bleiben. POSIX.1 legt eine Ausnahme fest: Falls SIGCHLD
          ignoriert wird, dann darf eine Implementierung die Zuordnung  unverändert  lassen  oder
          sie auf die Vorgabe zurücksetzen; Linux macht Ersteres.

       •  Alle   ausstehenden   asynchronen   E/A-Operationen  werden  abgebrochen  (aio_read(3),
          aio_write(3)).

       •  Für den Umgang mit Capabilities während execve(), siehe capabilities(7).

       •  Standardmäßig   bleiben   Dateideskriptoren   über   ein   execve()    hinweg    offen.
          Dateideskriptoren,  die  mit close-on-exec markiert sind, werden geschlossen; siehe die
          Beschreibung von FD_CLOEXEC in fcntl(2). (Falls ein Dateideskriptor  geschlossen  wird,
          führt dies zur Freigabe aller von der unterliegenden Datei durch den Prozess erhaltenen
          Datensatzsperren. Siehe fcntl(2) für Details.) Laut POSIX.1 darf das System eine  nicht
          festgelegte  Datei  für  jeden  der  Dateideskriptoren  0,  1 und 2 öffnen, falls diese
          andernfalls nach einem erfolgreichen execve() geschlossen und der Prozess aufgrund  der
          Modus-Bits  set-user-ID  oder  set-group-ID Privilegien erhalten würde. Als allgemeines
          Prinzip darf kein portables Programm, egal ob privilegiert oder nicht,  annehmen,  dass
          diese drei Dateideskriptoren über ein execve() geschlossen bleiben.

   Interpreter-Skripte
       Ein Interpreter-Skript ist eine Textdatei, die über Ausführrechte verfügt und dessen erste
       Zeile die folgende Form annimmt:

           #!Interpreter [Optionale-Arg]

       Der Interpreter muss ein gültiger Pfadname zu einer ausführbaren Datei sein.

       Falls das Argument  Pfadname  von  execve()  ein  Interpreterskript  festlegt,  dann  wird
       interpreter mit den folgenden Argumenten aufgerufen.

           Interpreter [Optionale-Arg] Pfadname Arg …

       Hierbei  ist  Pfadname  der  Pfadname  der  Datei,  die  als  erstes Argument von execve()
       festgelegt ist, und arg… die Serie von Wörtern, auf die vom  Argument  argv  von  execve()
       gezeigt wird, beginnen mit argv[1]. Beachten Sie, dass es keine Möglichkeit gibt, argv[0],
       der dem Aufruf execve() übergeben wurde, zu erhalten.

       Für den portablen Einsatz sollte Optionale-Arg entweder abwesend oder als  einzelnes  Wort
       angegeben  werden  (d.h.  es  sollte  keine  Leerraumzeichen enthalten); siehe ANMERKUNGEN
       unten.

       Seit Linux 2.6.28 erlaubt es der Kernel, dass der Interpreter eines Skripts selbst  wieder
       ein  Skript  ist. Diese Erlaubnis ist rekursiv bis zu einer Rekursionstiefe von 4, so dass
       der Interpreter ein Skript sein darf, das von  einem  Skript  interpretiert  wird  und  so
       weiter.

   Begrenzungen der Größe der Argumente und der Umgebung
       Die  meisten  UNIX-Implementierungen  verhängen  eine  Begrenzung  für die Gesamtgröße der
       Zeichenketten der Befehlszeilenargumente (argv) und der Umgebung (envp), die an ein  neues
       Programm übergeben werden darf. POSIX.1 erlaubt es einer Implementierung, diese Begrenzung
       mit der Konstante ARG_MAX  bekanntzugeben  (entweder  definiert  in  <limits.h>  oder  zur
       Laufzeit mit dem Aufruf sysconf(_SC_ARG_MAX) verfügbar).

       Vor   Linux   2.6.23   war   der   Speicher,   der   zum   Ablegen   der   Umgebungs-  und
       Argumentzeichenketten  verwandt  wurde,  auf  32  Seiten  begrenzt  (definiert  durch  die
       Kernelkonstante MAX_ARG_PAGES). Auf Architekturen mit einer 4-kB-Seitengröße führt dies zu
       einer Maximalgröße von 128 kB.

       Auf den meisten Architekturen wird unter Linux 2.6.23 und neuer eine Größenbegrenzung, die
       von  der  Ressourcenbegrenzung  RLIMIT_STACK  (siehe getrlimit(2)) abgeleitet ist, die zum
       Zeitpunkt  des  Aufrufs  execve()  in  Kraft   war,   unterstützt.   (Architekturen   ohne
       Speicherverwaltungseinheit  sind  die  Ausnahme:  bei ihnen bleibt die Begrenzung, die vor
       Linux 2.6.23 in Kraft war.) Diese  Änderung  erlaubt  es  Programmen,  eine  viel  größere
       Argumenten-  und/oder Umgebungsliste zu haben. Für diese Architekturen ist die Gesamtgröße
       auf 1/4 der erlaubten Stack-Größe begrenzt.  (Die  Erzwingung  der  1/4-Begrenzung  stellt
       sicher,  dass  neue  Programme  immer  über  Stack-Bereich  verfügen.) Zusätzlich wird die
       Gesamtgröße auf 3/4 des Wertes der Kernelkonstanten _STK_LIM (8 MiB) begrenzt. Seit  Linux
       2.6.25  stellt der Kernel auch eine Untergrenze von 32 Seiten dieser Begrenzung bereit, so
       dass selbst wenn RLIMIT_STACK sehr gering ist, Anwendungen garantiert über  mindestens  so
       viel  Argument-  und  Umgebungsbereich verfügen, wie dies unter Linux 2.6.22 und älter der
       Fall war. (Diese Garantie wurde nicht unter Linux 2.6.23 und 2.6.24  erfüllt.)  Zusätzlich
       ist  die  Begrenzung  pro Zeichenkette 32 Seiten (der Kernelkonstanten MAX_ARG_STRLEN) und
       die maximale Anzahl von Zeichenketten ist 0x7FFFFFFF.

RÜCKGABEWERT

       Im Erfolgsfall kehrt execve() nicht zurück, im  Fehlerfall  wird  -1  zurückgeliefert  und
       errno gesetzt, um den Fehler anzuzeigen.

FEHLER

       E2BIG  Die  Gesamtanzahl von Bytes in der Umgebungs- (envp) und der Argumentenliste (argv)
              ist zu groß.

       EACCES Für einen Teil des Pfadpräfixes von Pfadname oder dem Namen des Skript-Interpreters
              wird die Suchberechtigung verweigert. (Siehe auch path_resolution(7).)

       EACCES Die Datei oder der Skriptinterpreter ist keine reguläre Datei.

       EACCES Für  die  Datei  oder  ein Skript oder ELF-Interpreter wird die Ausführberechtigung
              verweigert.

       EACCES Das Dateisystem ist nicht noexec eingehängt.

       EAGAIN (seit Linux 3.1)
              Nach Änderung der realen UID mittels einer der Aufrufe  set*uid()  war  –  und  ist
              immer  noch  –  der  Aufrufende über seine Ressourcenbegrenzung RLIMIT_NPROC (siehe
              setrlimit(2)).  Für  eine   detailliertere   Erläuterung   dieses   Fehlers   siehe
              ANMERKUNGEN.

       EFAULT Pfadname oder einer der Zeiger in den Vektoren argv oder envp zeigt aus dem für Sie
              zugänglichen Adressraum heraus.

       EINVAL Ein ELF-Programm hat mehr als ein PT_INTERP-Segment (d.h. versuchte mehr als  einen
              Interpreter anzugeben).

       EIO    Es ist ein E/A-Fehler (engl. I/O) aufgetreten.

       EISDIR Ein ELF-Interpreter war ein Verzeichnis.

       ELIBBAD
              Ein ELF-Interpreter war in einem unbekannten Format.

       ELOOP  Beim  Auflösen  von  Pfadname  oder  dem  Namen eines Skripts oder ELF-Interpreters
              wurden zu viele symbolische Links ermittelt.

       ELOOP  Während der rekursiven  Skript-Interpretation  (siehe  »Interpreter-Skripte«  oben)
              wurde  die  maximale  Rekursionsbegrenzung  erreicht. Vor Linux 3.8 wurde in diesem
              Fall der Fehler ENOEXEC erstellt.

       EMFILE Die Beschränkung pro Prozess der Anzahl offener Datei-Deskriptoren wurde erreicht.

       ENAMETOOLONG
              Pfadname ist zu lang.

       ENFILE Die systemweite Beschränkung für die Gesamtzahl offener Dateien wurde erreicht.

       ENOENT Die Datei Pfadname oder ein Skript oder ELF-Interpreter existiert nicht.

       ENOEXEC
              Ein Programm ist nicht in einem erkennbaren Format, ist für die falsche Architektur
              oder hat einen anderen Formatfehler, wodurch es nicht ausgeführt werden kann.

       ENOMEM Es war nicht genügend Kernelspeicher verfügbar.

       ENOTDIR
              Ein  Teil  des  Pfadpräfixes  von Pfadname oder ein Skript oder ELF-Interpreter ist
              kein Verzeichnis.

       EPERM  Das Dateisystem ist nosuid eingehängt, der Benutzer ist nicht der Superuser und die
              Datei hat das Bit set-user-ID oder set-group-ID gesetzt.

       EPERM  Der  Prozess  wird verfolgt, der Benutzer ist nicht der Superuser und die Datei hat
              das Bit set-user-ID oder set-group-ID gesetzt.

       EPERM  Eine  »Capability-unfähige«  Anwendung  würde  nicht  die  ganze  Menge   der   vom
              ausführbaren    Programm   gewährten   erlaubten   Capabilities   erhalten.   Siehe
              capabilities(7).

       ETXTBSY
              Das angegebene Programm war für einen oder mehrere Prozesse zum Schreiben offen.

STANDARDS

       POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD. POSIX dokumentiert das  #!-Verhalten  nicht,  es
       existiert aber (mit einigen Variationen) auf anderen UNIX-Systemen.

ANMERKUNGEN

       Manchmal  wird  execve()  (und  die in exec(3) beschriebenen dazugehörigen Funktionen) als
       »Ausführung eines neuen Prozesses« (oder ähnlich) beschrieben. Dies  ist  eine  hochgradig
       irreführende  Beschreibung:  es gibt keinen neuen Prozess, viele Attribute des aufrufenden
       Prozesses bleiben unverändert (insbesondere seine  PID).  execve()  arrangiert  lediglich,
       dass ein existierender Prozess (der aufrufende Prozess) ein neues Programm ausführt.

       Set-user-ID- und Set-group-ID-Prozesse können nicht mit ptrace(2) verfolgt werden.

       Das  Ergebnis des Einhängens eines Dateisystems mit nosuid unterscheidet sich abhängig von
       der Linux-Kernelversion. Unter einigen wird die Ausführung von Programmen mit  set-user-ID
       und  set-group-ID  verweigert,  wenn  das  dem  Benutzer  Rechte geben würde, die er nicht
       bereits hatte (und EPERM zurückliefern). Unter anderen werden  die  Bits  set-user-ID  und
       set-group-ID ignoriert und exec() erfolgreich ausgeführt.

       Unter Linux können argv und envp als NULL festgelegt werden. In beiden Fällen hat dies den
       gleichen Effekt wie die Festlegung des Arguments auf einen Zeiger auf eine Liste, die  als
       einziges Element den NULL-Zeiger enthält. Nutzen Sie diese nicht standardisierte und nicht
       portable Misfunktionalität nicht aus! Unter vielen UNIX-Systemen führt die Festlegung  von
       argv  als  NULL  zu  einem  Fehler (EFAULT). Einige andere UNIX-Systeme behandeln den Fall
       envp==NULL wie Linux.

       POSIX.1 besagt, dass die von sysconf(3) zurückgelieferten Werte über die Lebensdauer eines
       Prozesses unveränderlich sein sollen. Seit 2.6.23 wird der von _SC_ARG_MAX berichtete Wert
       sich allerdings auch ändern, wenn die Ressourcenbegrenzung RLIMIT_STACK  sich  ändert,  um
       die  Tatsache  zu  berücksichtigen,  dass  die  Begrenzung  des  Platzes  zum  Halten  der
       Befehlszeilenargumente und der Umgebungsvariablen sich geändert hat.

       In den meisten  Fällen,  in  denen  execve()  fehlschlägt,  kehrt  die  Steuerung  zu  dem
       ursprünglichen  Abbild zurück und der Aufrufende von execve() kann mit dem Fehler umgehen.
       In (seltenen) Fällen kann  (typischerweise  durch  Ressourcenerschöpfung  verursacht)  der
       Fehlschlag  den  Punkt  ohne  Rückkehr  passieren:  das ursprüngliche Abbild wurde bereits
       entfernt aber das neue Abbild konnte  nicht  komplett  gebaut  werden.  In  diesen  Fällen
       beendet der Kernel den Prozess mit einem Signal SIGSEGV (SIGKILL bis Linux 3.17).

   Interpreter-Skripte
       Der Kernel legt eine maximal Länge für Text, der den Zeichen »#!« am Anfang eines Skriptes
       folgt, auf. Zeichen hinter dieser Begrenzung werden  ignoriert.  Vor  Linux  5.1  war  die
       Begrenzung 127 Zeichen, seit Linux 5.1 ist die Begrenzung 255 Zeichen.

       Die  Semantik  des  Arguments  Optionale-Args eines Interpreterskriptes unterscheidet sich
       zwischen Implementierungen. Unter Linux wird die  gesamte  Zeichenkette,  die  Interpreter
       folgt,  als  einziges  Argument  an  den Interpreter übergeben und diese Zeichenkette kann
       Leerzeichen enthalten. Das Verhalten unterscheidet sich aber auf einigen anderen Systemen.
       Einige  Systeme verwenden das erste Leerzeichen, um Optionale-Args zu beenden. Auf einigen
       Systemen  kann  ein  Interpreterskript  mehrere  Argumente  haben   und   Leerzeichen   in
       Optionale-Args werden zum Begrenzen der Argumente verwandt.

       Linux  (wie  die meisten anderen modernen UNIX-Systeme) ignoriert die Bits set-user-ID und
       set-group-ID bei Skripten.

   execve() und EAGAIN
       Eine detailliertere Beschreibung des Fehlers EAGAIN, der (seit Linux 3.1) beim Aufruf  von
       execve() auftreten kann, ist wie folgt:

       Der   Fehler  EAGAIN  kann  auftreten,  wenn  ein  vorhergehender  Aufruf  von  setuid(2),
       setreuid(2) oder setresuid(2) dazu führte, dass die reale  Benutzerkennung  des  Prozesses
       geändert    wurde   und   diese   Änderung   dazu   führte,   dass   der   Prozess   seine
       Ressourcenbeschränkung RLIMIT_NPROC überschritt (d.h. die Anzahl der zu der  neuen  realen
       UID gehörenden Prozesse überschreitet die Ressourcenbeschränkung). Von Linux 2.6.0 bis 3.0
       führte dies dazu,  dass  der  Aufruf  set*uid()  fehlschlug.  (Vor  Linux  2.6  wurde  die
       Ressourcenbeschränkung   bei   Prozessen,   die  ihre  Benutzerkennungen  änderten,  nicht
       durchgesetzt.)

       Seit Linux 3.1 schlägt in dem gerade beschriebenen Szenario  der  Aufruf  set*uid()  nicht
       mehr  fehl, da dies zu oft zu Sicherheitslöchern führte, bei denen fehlerhafte Anwendungen
       nicht den Rückgabewert prüften und annahmen, dass – falls der Aufrufende Root-Rechte hatte
       –  der  Aufruf immer erfolgreich sein würde. Stattdessen ändert der Aufruf set*uid() jetzt
       erfolgreich  die  reale  UID,  aber  der  Kernel  setzt  einen  internen  Schalter  namens
       PF_NPROC_EXCEEDED,   um   zu   vermerken,  dass  die  Ressourcenbeschränkung  RLIMIT_NPROC
       überschritten  wurde.  Falls  der  Schalter  PF_NPROC_EXCEEDED   gesetzt   ist   und   die
       Ressourcenbeschränkung   zum   Zeitpunkt   eines  folgenden  execve()-Aufrufs  immer  noch
       überschritten  ist,  dann  schlägt  dieser  Aufruf  mit  dem  Fehler  EAGAIN  fehl.  Diese
       Kernellogik  stellt  sicher, dass die Ressourcenbeschränkung RLIMIT_NPROC für den häufigen
       Ablauf bei privilegierten Daemons – also  fork(2)  +  set*uid()  +  execve()  –  weiterhin
       durchgesetzt wird.

       Falls die Ressourcenbegrenzung zum Zeitpunkt des Aufrufs execve() noch nicht überschritten
       wurde (da andere zu dieser realen UID gehörende Prozesse  sich  zwischen  dem  Aufruf  von
       set*uid()  und  dem Aufruf von execve() beendeten), dann gelingt der Aufruf und der Kernel
       bereinigt den Prozessschalter PF_NPROC_EXCEEDED. Der Schalter wird  auch  auf  0  gesetzt,
       falls ein folgender Aufruf von fork(2) durch diesen Prozess gelingt.

   Geschichtliches
       Unter  UNIX V6  wurde die Argumentenliste von einem exec()-Aufruf durch 0 beendet, während
       die Argumentenliste von main durch -1 beendet wurde. Daher war diese Argumentenliste nicht
       für weitere exec()-Aufrufe direkt verwendbar. Seit UNIX V7 sind beide NULL.

BEISPIELE

       Das  folgende  Programm  ist  dafür  gedacht, vom zweiten folgenden Programm ausgeführt zu
       werden. Es gibt nur seine Befehlszeile (eine pro Zeile) wieder aus.

           /* myecho.c */

           #include <stdio.h>
           #include <stdlib.h>

           int
           main(int argc, char *argv[])
           {
               for (size_t j = 0; j < argc; j++)
                   printf("argv[%zu]: %s\n", j, argv[j]);

               exit(EXIT_SUCCESS);
           }

       Dieses  Programm  kann  zur  Ausführung  des  in  seinem  Befehlszeilenargument  benannten
       Programms verwandt werden:

           /* execve.c */

           #include <stdio.h>
           #include <stdlib.h>
           #include <unistd.h>

           int
           main(int argc, char *argv[])
           {
               static char *newargv[] = { NULL, "Hallo", "Welt", NULL };
               static char *newenviron[] = { NULL };

               if (argc != 2) {
                printf(stderr, "Aufruf: %s <auszuführende-Datei>\n", argv[0]);
                exit(EXIT_FAILURE);
               }

               newargv[0] = argv[1];

               execve(argv[1], newargv, newenviron);
               perror("execve");   /* execve() kehrt nur im Fehlerfall zurück */
               exit(EXIT_FAILURE);
           }

       Wir können das zweite Programm verwenden, um das erste wie folgt aufzurufen:

           $ cc myecho.c -o myecho
           $ cc execve.c -o execve
           $ ./execve ./myecho
           argv[0]: ./myecho
           argv[1]: Hallo
           argv[2]: Welt

       Wir können diese Programme auch zur Demonstration der Verwendung eines Skript-Interpreters
       verwenden. Dafür erstellen wir ein Skript, dessen »Interpreter« unser myecho-Programm ist.

           $ cat > script
           #!./myecho script-arg
           ^D
           $ chmod +x script

       Wir können dann unser Programm verwenden, um das Skript auszuführen:

           $ ./execve ./script
           argv[0]: ./myecho
           argv[1]: script-arg
           argv[2]: ./script
           argv[3]: Hallo
           argv[4]: Welt

SIEHE AUCH

       chmod(2),  execveat(2),  fork(2),  get_robust_list(2),  ptrace(2),  exec(3),   fexecve(3),
       getauxval(3),   getopt(3),   system(3),   capabilities(7),   credentials(7),   environ(7),
       path_resolution(7), ld.so(8)

ÜBERSETZUNG

       Die   deutsche   Übersetzung   dieser   Handbuchseite   wurde   von    Helge    Kreutzmann
       <debian@helgefjell.de> erstellt.

       Diese  Übersetzung  ist  Freie  Dokumentation;  lesen  Sie  die GNU General Public License
       Version 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ oder neuer bezüglich der  Copyright-
       Bedingungen. Es wird KEINE HAFTUNG übernommen.

       Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-
       Mail an die Mailingliste der Übersetzer ⟨debian-l10n-german@lists.debian.org⟩.