Die Verzeichnisse /tmp
und /usr/tmp
(später /var/tmp
) war früher der Abladeplatz für alles und jeden. Der einzige Schutzmechanismus für Dateien in diesen Verzeichnissen ist das Sticky-Bit, das das Löschen oder Umbenennen von Dateien dort auf ihre Eigentümer beschränkt. Wie Marcelm in einem Kommentar betonte, hindert im Prinzip nichts jemanden daran, Dateien mit Namen zu erstellen, die von Diensten verwendet werden (wie nginx.pid
oder sshd.pid
). (In der Praxis könnten die Startskripte solche gefälschten Dateien jedoch zuerst entfernen.)
/run
wurde für nicht persistente Laufzeitdaten langlebiger Dienste wie Sperren, Sockets, PID-Dateien und dergleichen eingerichtet. Da es für die Öffentlichkeit nicht beschreibbar ist, schützt es Dienstlaufzeitdaten vor dem Durcheinander in /tmp
und Jobs, die dort aufräumen. In der Tat:Zwei Distributionen, die ich betreibe (kein Wortspiel beabsichtigt), haben die Berechtigungen 755 auf /run
, während /tmp
und /var/tmp
(und /dev/shm
übrigens) haben die Berechtigungen 1777.
/tmp
ist der Speicherort für die Erstellung temporärer Dateien und Verzeichnisse. Es kann nicht zum Speichern von "bekannten Namen" verwendet werden (dh Namen, die ein anderer Prozess kennen könnte, ohne dass Sie ihm den Namen irgendwie übermitteln müssen), da niemand Eigentümer des Namensraums ist. Jeder kann dort Dateien erstellen. Als solches verwenden Sie es im Allgemeinen, wenn Sie ein Dienstprogramm haben, das eine Datei (d. h. keine Pipe oder dergleichen) als Eingabe oder Ausgabe benötigt, wobei jeder (zufällig generierte) Name funktioniert, solange Sie den Namen übergeben.
In der Vergangenheit haben einige Dinge (wie X) gegen dieses Prinzip verstoßen und bekannte Namen (wie .X11-unix
) in /tmp
. Dies ist natürlich fehlerhaft und ermöglicht es jedem Benutzer, den Dienst zu tun, der dies tun muss, indem er einfach versucht, zuerst eine Datei mit dem gewünschten Namen zu erstellen. Solche Dinge gehören unter /run
(oder äquivalent /var/run
wenn Sie den Revisionismus von Freedesktop.org nicht abonnieren). Noch besser wäre es natürlich, sie so zu fixieren, dass sie keine bekannten Namen in einem globalen Namensraum verwenden, sondern stattdessen einen Pfadnamen weitergeben.
Kein Grund, sowohl /run als auch /tmp zu haben
Ich denke, du hast recht. /tmp
ist im Wesentlichen veraltet, jetzt haben wir /run
. Wenn Ihr Programm dazu in der Lage ist (was voraussetzt, dass es installiert wurde als privilegierte Operation), dann würden Sie heutzutage ein Unterverzeichnis von /run
verwenden . Dies ist aus Sicherheitsgründen.
Z.B. Der CUPS-Druck-Daemon wird nicht als Root ausgeführt, sondern im Allgemeinen von einem Betriebssystempaket installiert. Das Paket installiert /usr/lib/tmpfiles.d/cups.conf
, und systemd-tmpfiles
erstellt ein Verzeichnis, auf das es zugreifen kann. Da das Verzeichnis unter /run
liegt , kann der Name im Gegensatz zu /tmp
nicht böswillig von einem nicht privilegierten Benutzer beansprucht worden sein die weltweit beschreibbar ist.
"Nicht privilegierte Programme", die /run
nicht verwenden können direkt
Der wirkliche Unterschied besteht darin, ob Ihr Programm von einem willkürlichen, nicht privilegierten Benutzer unter seiner eigenen Benutzer-ID ausgeführt wird. Aber /tmp
möchten Sie im Allgemeinen trotzdem nicht verwenden , da andere nicht privilegierte Benutzer darauf zugreifen können. Sie würden lieber $XDG_RUNTIME_DIR
verwenden . Typischerweise wird dies als /run/user/$(id -u)
implementiert - es ist also zufällig ein Unterverzeichnis von /run
auch. Der Standort ist jedoch nicht garantiert; Programme sollten immer die Umgebungsvariable verwenden.
/tmp
wäre nur für die Ad-hoc-Zusammenarbeit zwischen verschiedenen nicht privilegierten Benutzern auf dem System nützlich. Solche Ad-hoc-Systeme sind anfällig für einen böswilligen Benutzer, der sich weigert zu kooperieren und Dinge für alle verdirbt :). Ein Beispiel wären unprivilegierte Benutzer, die sich entscheiden, eine Version von talk
auszuführen Daemon, der einen Unix-Socket verwendet.
Originalinformation von Lennart Poettering
Beachten Sie, dass Poetterings Checkliste unten behauptet, dass /tmp
wäre für "kleine Dateien" sinnvoll, wohingegen /run
sollte nur für "Kommunikationsprimitive" verwendet werden. Ich glaube auch nicht, dass diese Unterscheidung stimmt. Der Aushängeschild für /run
ist udev
, und ich bin mir ziemlich sicher /run/udev
enthält interne Datenbanken . Sobald Sie einen /run
haben Verzeichnis, ich glaube nicht, dass irgendjemand der behaupteten Unterscheidung folgen und einen weiteren erstellen möchte Verzeichnis, um /tmp
durcheinander zu bringen . In der Praxis verwenden wir also einfach /run
heutzutage.
Die Verwendung von weltweit beschreibbaren Shared Namespaces [wie /tmp] für Kommunikationszwecke war schon immer problematisch, da man stabile Namen braucht, um eine Kommunikation herzustellen, aber stabile Namen öffnen die Türen für DoS-Angriffe. Dies kann teilweise korrigiert werden, indem geschützte Pro-App-Verzeichnisse für bestimmte Dienste während des frühen Bootens eingerichtet werden (wie wir es für X11 tun), aber dies behebt das Problem nur teilweise, da dies nur korrekt funktioniert, wenn auf jede Paketinstallation ein Neustart folgt.
...
Ein weiteres Fedora-Feature (für Fedora 17) änderte die Semantik von /tmp für viele Systemdienste, um sie sicherer zu machen, indem die /tmp-Namespaces der verschiedenen Dienste isoliert wurden
...
Da /tmp nicht mehr unbedingt ein gemeinsam genutzter Namensraum ist, ist er im Allgemeinen als Ort für Kommunikationsprimitive ungeeignet.
...
[/run] ist garantiert ein tmpfs und wird daher beim Booten automatisch gespült. Darüber hinaus findet keine automatische Bereinigung statt.
...
Hier ist eine grobe Anleitung, wie wir Ihnen (einem Linux-Anwendungsentwickler) empfehlen, das richtige Verzeichnis auszuwählen:
- Sie brauchen einen Ort, an dem Sie Ihren Socket (oder ein anderes Kommunikationselement) ablegen können, und Ihr Code wird privilegiert ausgeführt:Verwenden Sie ein Unterverzeichnis unter /run. (Oder unter /var/run für zusätzliche Kompatibilität.)
- Sie brauchen einen Ort, an dem Sie Ihren Socket (oder ein anderes Kommunikationselement) ablegen können, und Ihr Code wird unprivilegiert ausgeführt:Verwenden Sie ein Unterverzeichnis unterhalb von $XDG_RUNTIME_DIR.
- Sie brauchen einen Ort, an dem Sie Ihre größeren Downloads und laufenden Downloads ablegen und unprivilegiert ausführen können:Verwenden Sie $XDG_DOWNLOAD_DIR.
- Sie brauchen einen Ort, um Cache-Dateien abzulegen, die persistent sein und unprivilegiert ausgeführt werden sollen:Verwenden Sie $XDG_CACHE_HOME.
- Nichts des Obigen trifft zu und Sie müssen eine kleine Datei platzieren, die keine Persistenz benötigt:Verwenden Sie $TMPDIR mit einem Fallback auf /tmp. Und verwenden Sie mkstemp() und mkdtemp() und nichts Eigenes.
- Verwenden Sie andernfalls $TMPDIR mit einem Fallback auf /var/tmp. Verwenden Sie auch mkstemp()/mkdtemp().
Beachten Sie, dass diese obigen Regeln nur von uns vorgeschlagen werden. Diese Regeln berücksichtigen alles, was wir zu diesem Thema wissen, und vermeiden Probleme mit aktuellen und zukünftigen Distributionen, soweit wir sie sehen können. Bitte erwägen Sie, Ihre Projekte zu aktualisieren, um diesen Regeln zu folgen, und denken Sie daran, wenn Sie neuen Code schreiben.
Eine Sache, die wir betonen möchten, ist, dass /tmp und /var/tmp meistens nicht die richtige Wahl für Ihren Anwendungsfall sind. Es gibt gültige Verwendungen für diese Verzeichnisse, aber oft ist ein anderes Verzeichnis tatsächlich der bessere Ort. Seien Sie also vorsichtig, ziehen Sie die anderen Optionen in Betracht, aber wenn Sie sich für /tmp oder /var/tmp entscheiden, dann stellen Sie zumindest sicher, dass Sie mkstemp()/mkdtemp() verwenden.
Wir kommen irgendwie mit dem alten Ich habe /tmp
davon Socket, der vom X-Window-System verwendet wird, wie oben beschrieben.tmpfiles.d/x11.conf
falsch verstanden . Sieht eher so aus, als würde es auf Zusammenarbeit angewiesen sein :). Ich gehe davon aus, dass der Code geprüft wurde, sodass Denial-of-Service das Schlimmste ist, was passieren kann.