Was macht das FD_CLOEXEC fcntl () Flag?

82

Wie so:

if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
...

Obwohl ich gelesen habe man fcntl, kann ich nicht herausfinden, was es tut.

Compile-Fan
quelle

Antworten:

73

Es setzt das Close-on-Exec- Flag für den Dateideskriptor, wodurch der Dateideskriptor automatisch (und atomar) geschlossen wird, wenn eine der execFunktionen der Familie erfolgreich ist.

Außerdem wird der Rückgabewert getestet, um festzustellen, ob die Operation fehlgeschlagen ist. Dies ist eher nutzlos, wenn der Dateideskriptor gültig ist, da es keine Bedingung gibt, unter der diese Operation bei einem gültigen Dateideskriptor fehlschlagen sollte.

R .. GitHub HÖREN SIE AUF, EIS ZU HELFEN
quelle
4
Beachten Sie, dass es nichts gegen das Löschen von Dateistreams ( FILE *) unternimmt, die dem Dateideskriptor zugeordnet sind. Eine gültige Verwendung für FD_CLOEXEC ist das Schließen einer Protokolldatei, die der übergeordnete Prozess beim Ausführen eines Shell-Prozesses geöffnet hat. Beachten Sie, dass POSIX 2008 eine Option open(2)für O_CLOEXEC bietet. Sie können diese Eigenschaft also beim Öffnen der Datei festlegen. Dies ist sehr nützlich, sobald sie allgemein verfügbar ist.
Jonathan Leffler
Das atomare Setzen des Flags beim Öffnen der Datei ist für jedes Thread-Programm, das möglicherweise Dateien öffnet, während ein anderer Thread möglicherweise externe Programme ausführt, ziemlich wichtig. Leider ist es nur für openund nicht accept, socket, pipeusw ...
R .. GitHub STOPP HILFT ICE
Ja - es gibt Design - Probleme Hinzufügen O_CLOEXEC oder äquivalent zu den anderen Datei-Beschreiber Funktionen zu schaffen (wenn auch dup()und dup2()sind davon nicht betroffen, natürlich). Sie müssten wahrscheinlich neue Funktionen mit einem zusätzlichen Parameter 'mode' oder 'flags' haben, was vermutlich der Grund ist, warum dies nicht geschehen ist. Wenn Sie O_CLOEXEC für den Socket verwenden könnten, könnten Sie annehmen, dass accept()dieses Flag auf dem zurückgegebenen Deskriptor geklont wird . Aber socket()und pipe()sind kniffliger.
Jonathan Leffler
3
dupund dup2sind betroffen. Das Close-on-Exec-Flag gilt für Dateideskriptoren, nicht für geöffnete Dateibeschreibungen, sodass es nicht für doppelte Dateideskriptoren freigegeben wird. Das ist eine sehr gute Sache.
R .. GitHub STOP HELPING ICE
3
Im Anschluss an das Gespräch in den Kommentaren, POSIX hat für die Aufnahme in die nächste Ausgabe neuer Schnittstellen angenommen , die die Mängel zu beheben: dup3, pipe2, und accept4. Hat socketauch das SOCK_CLOEXECFlag, das Sie mit dem angeforderten Socket-Typ kombinieren können.
R .. GitHub STOP HELPING ICE
33

Es markiert den Dateideskriptor so, dass er close()automatisch aktiviert wird, wenn der Prozess oder fork()untergeordnete Elemente eine exec*()der Funktionsfamilien aufrufen. Dies ist nützlich, um zu verhindern, dass Ihre Dateideskriptoren an zufällige Programme weitergegeben werden, die z system().

Geekosaurier
quelle
Ist das ein Sicherheitsrisiko?
Zach
1
@zach könnte man so sagen; Aber wirklich jedes Refactoring, das Sie durchführen, wie das Einkapseln einer verstreuten Logik in eine einzelne Entität, kann als "Sicherheitsbedenken" bezeichnet werden, da es die Wahrscheinlichkeit von Fehlern aufgrund der falschen Verwendung dieser Entität verringert und "ein Fehler" eine abstrakte Sache ist Dies schließt insbesondere Segfaults und Informationslecks ein.
Hi-Angel
Ich überarbeite also einen Socket-Code und zwischen dem Abrufen des Sockets und dem Verbinden mit dem Remote-Server verwenden sie F_SETFD, um das FD_CLOEXEC-Flag zum FD des Sockets hinzuzufügen. Nach einer erfolgreichen Verbindung wird dann die FD_CLOEXEC entfernt. Ich kann keine exec () -Aufrufe in diesem Codebereich finden und frage mich, ob es sich um Reste von altem Code handelt, die hätten entfernt werden sollen, aber nicht entfernt wurden. Ich bin mir nicht sicher, wonach ich suchen soll, um den Zweck des Ganzen herauszufinden.
JoeManiaci