Was macht das Flag FD_CLOEXEC fcntl()?

Lesezeit: 4 Minuten

Benutzeravatar von compile-fan
Compiler-Fan

So:

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

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

Es setzt die close-on-exec Flag für den Dateideskriptor, wodurch der Dateideskriptor automatisch (und atomar) geschlossen wird, wenn einer der exec-Familienfeiern gelingen.

Es testet auch den Rückgabewert, um zu sehen, ob die Operation fehlgeschlagen ist, was ziemlich nutzlos ist, wenn der Dateideskriptor gültig ist, da es keine Bedingung gibt, unter der diese Operation bei einem gültigen Dateideskriptor fehlschlagen sollte.

  • Beachten Sie, dass es nichts über das Leeren von Dateistreams (FILE *), die dem Dateideskriptor zugeordnet sind. Eine gültige Verwendung für FD_CLOEXEC besteht darin, eine Protokolldatei zu schließen, die der übergeordnete Prozess geöffnet hat, wenn ein Shell-Prozess ausgeführt wird. Beachten Sie, dass POSIX 2008 eine Option dazu hat open(2) für O_CLOEXEC – Sie können diese Eigenschaft also beim Öffnen der Datei festlegen, was sehr nützlich sein wird, sobald sie allgemein verfügbar ist.

    – Jonathan Leffler

    25. Mai 2011 um 14:11 Uhr

  • 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 externe Programme ausführt, ziemlich wichtig. Leider nur für verfügbar open und nicht accept, socket, pipeetc…

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    25. Mai 2011 um 14:19 Uhr

  • Ja – es gibt Designprobleme beim Hinzufügen von O_CLOEXEC oder Äquivalenten zu den anderen Funktionen zum Erstellen von Dateideskriptoren (obwohl dup() und dup2() sind natürlich nicht betroffen). Sie müssten wahrscheinlich neue Funktionen mit einem zusätzlichen ‘mode’- oder ‘flags’-Parameter haben, was vermutlich der Grund dafür ist, dass es nicht passiert ist. Wenn Sie O_CLOEXEC für Sockets verwenden könnten, könnten Sie das annehmen accept() würde dieses Flag auf dem Deskriptor klonen, den es zurückgibt. Aber socket() und pipe() sind kniffliger.

    – Jonathan Leffler

    25. Mai 2011 um 14:27 Uhr

  • dup und dup2 sind betroffen. Das close-on-exec-Flag gilt für Dateideskriptoren, nicht für offene Dateibeschreibungen, daher wird es nicht von duplizierten Dateideskriptoren gemeinsam genutzt. Das ist eine sehr gute Sache.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    25. Mai 2011 um 14:33 Uhr

  • Nach dem Gespräch in den Kommentaren hat POSIX neue Schnittstellen zur Aufnahme in die nächste Ausgabe angenommen, die die Mängel beheben: dup3, pipe2und accept4. Ebenfalls, socket hat die SOCK_CLOEXEC Flag können Sie mit dem gewünschten Steckdosentyp kombinieren.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    10. März 2014 um 16:30 Uhr

Es markiert den Dateideskriptor so, dass es sein wird close()d automatisch, wenn der Prozess oder alle Kinder es fork()s ruft einer der an exec*() Familie von Funktionen. Dies ist nützlich, um zu verhindern, dass Ihre Dateideskriptoren an zufällige Programme weitergegeben werden, die z system().

  • Ist dies ein Sicherheitsproblem?

    – zach

    29. Juli 2017 um 11:14 Uhr

  • @zach könnte man so sagen; Aber dann kann wirklich jedes Refactoring, das Sie durchführen, wie das Einkapseln einer verstreuten Logik in eine einzelne Entität, als “Sicherheitsbedenken” bezeichnet werden, da es die Wahrscheinlichkeit von Fehlern aufgrund einer falschen Verwendung dieser Entität verringert und “ein Fehler” eine abstrakte Sache ist dazu gehören insbesondere Segfaults und Informationslecks.

    – Hallo Engel

    10. Januar 2019 um 22:23 Uhr

  • Also refaktoriere ich etwas 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. Dann wird nach einer erfolgreichen Verbindung die FD_CLOEXEC entfernt. Ich kann keine exec()-Aufrufe finden, die an diesem Codebereich beteiligt sind, und ich frage mich, ob es sich um Überbleibsel von altem Code handelt, der hätte entfernt werden sollen, es aber nicht waren. Ich bin mir nicht sicher, wonach ich suchen soll, um den Zweck des Ganzen herauszufinden.

    – JoeManiaci

    17. August 2020 um 20:57 Uhr

Benutzeravatar von Gangfeng Huang
Gangfeng Huang

Beachten Sie, dass die Verwendung dieses Flags in einigen Multithread-Programmen unerlässlich ist, da die Verwendung eines separaten fcntl(2) F_SETFD Vorgang zum Einstellen der FD_CLOEXEC flag reicht nicht aus, um Race-Conditions zu vermeiden, bei denen ein Thread einen Dateideskriptor öffnet und versucht, sein close-on-exec-Flag zu setzen fcntl(2) zur gleichen Zeit wie ein anderer Thread a fork(2) Plus execve(2). Abhängig von der Ausführungsreihenfolge kann das Rennen zu dem Dateideskriptor führen, der von zurückgegeben wird open() unbeabsichtigt an das Programm weitergegeben wird, das von dem untergeordneten Prozess ausgeführt wird, der von erstellt wurde fork(2).

(Diese Art von Race ist im Prinzip für jeden Systemaufruf möglich, der einen Dateideskriptor erstellt, dessen Close-on-exec-Flag gesetzt werden sollte, und verschiedene andere Linux-Systemaufrufe bieten ein Äquivalent des O_CLOEXEC kennzeichnen, um dieses Problem zu lösen.)

1420080cookie-checkWas macht das Flag FD_CLOEXEC fcntl()?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy